ldap/servers
by Richard Allen Megginson
ldap/servers/slapd/connection.c | 1 +
ldap/servers/slapd/daemon.c | 7 +++++++
ldap/servers/slapd/proto-slap.h | 1 +
3 files changed, 9 insertions(+)
New commits:
commit df93b03da12c22d18a4153105f687671e52efdd5
Author: Matthew Via <matthew.via(a)mailtrust.com>
Date: Wed Jul 10 11:30:57 2013 -0600
Ticket #47428 - Memory leak in 389-ds-base 1.2.11.15
https://fedorahosted.org/389/ticket/47428
Reviewed by: rmeggins
Branch: master
Fix Description: Call ber_sockbuf_remove_io to remove our openldap io layer
from the connection c_sb and free the data associated with it.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
index 687bf42..b2ed83c 100644
--- a/ldap/servers/slapd/connection.c
+++ b/ldap/servers/slapd/connection.c
@@ -263,6 +263,7 @@ connection_cleanup(Connection *conn)
/* destroy any sasl context */
sasl_dispose((sasl_conn_t**)&conn->c_sasl_conn);
/* PAGED_RESULTS */
+ handle_closed_connection(conn); /* Clean up sockbufs */
pagedresults_cleanup(conn, 0 /* do not need to lock inside */);
/* free the connection socket buffer */
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index e0c14c8..817fea7 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -2593,6 +2593,13 @@ bail:
#endif /* ENABLE_AUTOBIND */
#endif /* ENABLE_LDAPI */
+void
+handle_closed_connection(Connection *conn)
+{
+ ber_sockbuf_remove_io(conn->c_sb, &openldap_sockbuf_io,
+ LBER_SBIOD_LEVEL_PROVIDER);
+}
+
/* NOTE: this routine is not reentrant */
static int
handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, int secure, int local)
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index dc73faa..447d7d5 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -1413,6 +1413,7 @@ int sasl_io_setup(Connection *c);
/*
* daemon.c
*/
+void handle_closed_connection(Connection *);
#ifndef LINUX
void slapd_do_nothing(int);
#endif
10 years, 10 months
Branch '389-ds-base-1.3.0' - ldap/servers
by Richard Allen Megginson
ldap/servers/slapd/connection.c | 1 +
ldap/servers/slapd/daemon.c | 7 +++++++
ldap/servers/slapd/proto-slap.h | 1 +
3 files changed, 9 insertions(+)
New commits:
commit b18ee0b41fbcc901ed2a9b5c0431708e452a40c6
Author: Matthew Via <matthew.via(a)mailtrust.com>
Date: Wed Jul 10 11:30:57 2013 -0600
Ticket #47428 - Memory leak in 389-ds-base 1.2.11.15
https://fedorahosted.org/389/ticket/47428
Reviewed by: rmeggins
Branch: 389-ds-base-1.3.0
Fix Description: Call ber_sockbuf_remove_io to remove our openldap io layer
from the connection c_sb and free the data associated with it.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
(cherry picked from commit df93b03da12c22d18a4153105f687671e52efdd5)
(cherry picked from commit ed26da0722a23a50fb286e8bc57ec4fea8dde4a2)
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
index ca64f21..aa02aa3 100644
--- a/ldap/servers/slapd/connection.c
+++ b/ldap/servers/slapd/connection.c
@@ -203,6 +203,7 @@ connection_cleanup(Connection *conn)
/* destroy any sasl context */
sasl_dispose((sasl_conn_t**)&conn->c_sasl_conn);
/* PAGED_RESULTS */
+ handle_closed_connection(conn); /* Clean up sockbufs */
pagedresults_cleanup(conn, 0 /* do not need to lock inside */);
/* free the connection socket buffer */
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index 4fbfd9d..3cce290 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -2592,6 +2592,13 @@ bail:
#endif /* ENABLE_AUTOBIND */
#endif /* ENABLE_LDAPI */
+void
+handle_closed_connection(Connection *conn)
+{
+ ber_sockbuf_remove_io(conn->c_sb, &openldap_sockbuf_io,
+ LBER_SBIOD_LEVEL_PROVIDER);
+}
+
/* NOTE: this routine is not reentrant */
static int
handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, int secure, int local)
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 788cd16..50f399a 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -1391,6 +1391,7 @@ int sasl_io_setup(Connection *c);
/*
* daemon.c
*/
+void handle_closed_connection(Connection *);
#ifndef LINUX
void slapd_do_nothing(int);
#endif
10 years, 10 months
Branch '389-ds-base-1.2.11' - ldap/servers
by Richard Allen Megginson
ldap/servers/slapd/connection.c | 1 +
ldap/servers/slapd/daemon.c | 7 +++++++
ldap/servers/slapd/proto-slap.h | 1 +
3 files changed, 9 insertions(+)
New commits:
commit 6e0a8efb16a1651387623ce997c021f0460d2788
Author: Matthew Via <matthew.via(a)mailtrust.com>
Date: Wed Jul 10 11:30:57 2013 -0600
Ticket #47428 - Memory leak in 389-ds-base 1.2.11.15
https://fedorahosted.org/389/ticket/47428
Reviewed by: rmeggins
Branch: 389-ds-base-1.2.11
Fix Description: Call ber_sockbuf_remove_io to remove our openldap io layer
from the connection c_sb and free the data associated with it.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
(cherry picked from commit df93b03da12c22d18a4153105f687671e52efdd5)
(cherry picked from commit ed26da0722a23a50fb286e8bc57ec4fea8dde4a2)
(cherry picked from commit b18ee0b41fbcc901ed2a9b5c0431708e452a40c6)
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
index 1d1adac..914a2d3 100644
--- a/ldap/servers/slapd/connection.c
+++ b/ldap/servers/slapd/connection.c
@@ -203,6 +203,7 @@ connection_cleanup(Connection *conn)
/* destroy any sasl context */
sasl_dispose((sasl_conn_t**)&conn->c_sasl_conn);
/* PAGED_RESULTS */
+ handle_closed_connection(conn); /* Clean up sockbufs */
pagedresults_cleanup(conn, 0 /* do not need to lock inside */);
/* free the connection socket buffer */
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index d6604a7..a392398 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -2590,6 +2590,13 @@ bail:
#endif /* ENABLE_AUTOBIND */
#endif /* ENABLE_LDAPI */
+void
+handle_closed_connection(Connection *conn)
+{
+ ber_sockbuf_remove_io(conn->c_sb, &openldap_sockbuf_io,
+ LBER_SBIOD_LEVEL_PROVIDER);
+}
+
/* NOTE: this routine is not reentrant */
static int
handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, int secure, int local)
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 08edeb0..fec7ee5 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -1380,6 +1380,7 @@ int sasl_io_setup(Connection *c);
/*
* daemon.c
*/
+void handle_closed_connection(Connection *);
#ifndef LINUX
void slapd_do_nothing(int);
#endif
10 years, 10 months
ldap/servers
by Richard Allen Megginson
ldap/servers/plugins/replication/repl5.h | 4
ldap/servers/plugins/replication/repl5_plugins.c | 29 ++++-
ldap/servers/plugins/replication/repl5_replica.c | 84 ++++++++++++----
ldap/servers/plugins/replication/repl5_replica_config.c | 4
ldap/servers/plugins/replication/repl5_ruv.c | 55 ++++++----
ldap/servers/plugins/replication/repl5_ruv.h | 1
ldap/servers/slapd/back-ldbm/ldbm_add.c | 31 +++--
ldap/servers/slapd/back-ldbm/ldbm_delete.c | 32 +++---
ldap/servers/slapd/back-ldbm/ldbm_modify.c | 32 +++---
ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 31 +++--
ldap/servers/slapd/back-ldbm/misc.c | 1
11 files changed, 205 insertions(+), 99 deletions(-)
New commits:
commit dace0f15c0b19efbd6af3ef2d1a8f7992b90c140
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Tue Jul 9 11:38:39 2013 -0600
Ticket #47392 - ldbm errors when adding/modifying/deleting entries
https://fedorahosted.org/389/ticket/47392
Reviewed by: lkrispenz (Thanks!)
Branch: master
Fix Description: The problem is caused by cache consistency issues with the
RUV entry. Before the txn starts, we grab a pointer to the RUV entry in
the cache. When DNA (or any betxnpreop plugin) updates the database, it
will also grab a pointer to the cached RUV entry and modify it, out from
under the parent txn. This can also cause the max CSN in the RUV to go
backwards - the nested txn will have a later CSN which will be
overwritten by the earlier CSN from the parent txn.
The fix is to move the ldbm_ruv_txn code inside the transaction loop after
the betxnpreop plugins have been run. Also have to add modify_term inside
the retry logic to cancel the modify ruv txn stuff in order to retry.
The other part of the fix is to tell the code that updates the max CSN
in the RUV to skip changes that would cause the RUV to go backwards,
and return a code to the caller that tells the caller that the CSN is
already covered. The code that updates the RUV for the txn will skip
the modify operations in that case.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index 8da2d3b..0fa7ee4 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -558,7 +558,7 @@ void replica_replace_flags (Replica *r, PRUint32 flags);
void replica_dump(Replica *r);
void replica_set_enabled (Replica *r, PRBool enable);
Object *replica_get_replica_from_dn (const Slapi_DN *dn);
-void replica_update_ruv(Replica *replica, const CSN *csn, const char *replica_purl);
+int replica_update_ruv(Replica *replica, const CSN *csn, const char *replica_purl);
Object *replica_get_replica_for_op (Slapi_PBlock *pb);
/* the functions below manipulate replica hash */
int replica_init_name_hash ();
@@ -591,8 +591,8 @@ void replica_set_purge_delay (Replica *r, PRUint32 purge_delay);
void replica_set_tombstone_reap_interval (Replica *r, long interval);
void replica_update_ruv_consumer (Replica *r, RUV *supplier_ruv);
void replica_set_ruv_dirty (Replica *r);
-void replica_write_ruv (Replica *r);
Slapi_Entry *get_in_memory_ruv(Slapi_DN *suffix_sdn);
+int replica_write_ruv (Replica *r);
char *replica_get_dn(Replica *r);
void replica_check_for_tasks(Replica*r, Slapi_Entry *e);
void replica_update_state (time_t when, void *arg);
diff --git a/ldap/servers/plugins/replication/repl5_plugins.c b/ldap/servers/plugins/replication/repl5_plugins.c
index 5981d0c..5d1a776 100644
--- a/ldap/servers/plugins/replication/repl5_plugins.c
+++ b/ldap/servers/plugins/replication/repl5_plugins.c
@@ -1114,14 +1114,15 @@ copy_operation_parameters(Slapi_PBlock *pb)
* locally-processed update. This is called for both replicated
* and non-replicated operations.
*/
-static void
+static int
update_ruv_component(Replica *replica, CSN *opcsn, Slapi_PBlock *pb)
{
PRBool legacy;
char *purl;
+ int rc = RUV_NOTFOUND;
if (!replica || !opcsn)
- return;
+ return rc;
/* Replica configured, so update its ruv */
legacy = replica_is_legacy_consumer (replica);
@@ -1130,12 +1131,13 @@ update_ruv_component(Replica *replica, CSN *opcsn, Slapi_PBlock *pb)
else
purl = (char*)replica_get_purl_for_op (replica, pb, opcsn);
- replica_update_ruv(replica, opcsn, purl);
+ rc = replica_update_ruv(replica, opcsn, purl);
if (legacy)
{
slapi_ch_free ((void**)&purl);
}
+ return rc;
}
/*
@@ -1297,11 +1299,30 @@ write_changelog_and_ruv (Slapi_PBlock *pb)
just read from the changelog in either the supplier or consumer ruv
*/
if (0 == return_value) {
+ char csn_str[CSN_STRSIZE];
CSN *opcsn;
+ int rc;
slapi_pblock_get( pb, SLAPI_OPERATION, &op );
opcsn = operation_get_csn(op);
- update_ruv_component(r, opcsn, pb);
+ rc = update_ruv_component(r, opcsn, pb);
+ if (RUV_COVERS_CSN == rc) {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "write_changelog_and_ruv: RUV already covers csn for "
+ "%s (uniqid: %s, optype: %lu) csn %s\n",
+ REPL_GET_DN(&op_params->target_address),
+ op_params->target_address.uniqueid,
+ op_params->operation_type,
+ csn_as_string(op_params->csn, PR_FALSE, csn_str));
+ } else if (rc != RUV_SUCCESS) {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+ "write_changelog_and_ruv: failed to update RUV for "
+ "%s (uniqid: %s, optype: %lu) to changelog csn %s\n",
+ REPL_GET_DN(&op_params->target_address),
+ op_params->target_address.uniqueid,
+ op_params->operation_type,
+ csn_as_string(op_params->csn, PR_FALSE, csn_str));
+ }
}
object_release (repl_obj);
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
index 8121901..5aa58f0 100644
--- a/ldap/servers/plugins/replication/repl5_replica.c
+++ b/ldap/servers/plugins/replication/repl5_replica.c
@@ -665,10 +665,11 @@ replica_set_ruv (Replica *r, RUV *ruv)
* inbound replication session operation, and needs to update its
* local RUV.
*/
-void
+int
replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl)
{
char csn_str[CSN_STRSIZE];
+ int rc = RUV_SUCCESS;
PR_ASSERT(NULL != r);
PR_ASSERT(NULL != updated_csn);
@@ -681,11 +682,13 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl)
{
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_update_ruv: replica "
"is NULL\n");
+ rc = RUV_BAD_DATA;
}
else if (NULL == updated_csn)
{
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_update_ruv: csn "
"is NULL when updating replica %s\n", slapi_sdn_get_dn(r->repl_root));
+ rc = RUV_BAD_DATA;
}
else
{
@@ -718,8 +721,17 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl)
}
}
/* Update max csn for local and remote replicas */
- if (ruv_update_ruv (ruv, updated_csn, replica_purl, rid == r->repl_rid)
- != RUV_SUCCESS)
+ rc = ruv_update_ruv (ruv, updated_csn, replica_purl, rid == r->repl_rid);
+ if (RUV_COVERS_CSN == rc)
+ {
+ slapi_log_error(SLAPI_LOG_REPL,
+ repl_plugin_name, "replica_update_ruv: RUV "
+ "for replica %s already covers max_csn = %s\n",
+ slapi_sdn_get_dn(r->repl_root),
+ csn_as_string(updated_csn, PR_FALSE, csn_str));
+ /* RUV is not dirty - no write needed */
+ }
+ else if (RUV_SUCCESS != rc)
{
slapi_log_error(SLAPI_LOG_FATAL,
repl_plugin_name, "replica_update_ruv: unable "
@@ -727,14 +739,18 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl)
slapi_sdn_get_dn(r->repl_root),
csn_as_string(updated_csn, PR_FALSE, csn_str));
}
-
- r->repl_ruv_dirty = PR_TRUE;
+ else
+ {
+ /* RUV updated - mark as dirty */
+ r->repl_ruv_dirty = PR_TRUE;
+ }
}
else
{
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
"replica_update_ruv: unable to get RUV object for replica "
"%s\n", slapi_sdn_get_dn(r->repl_root));
+ rc = RUV_NOTFOUND;
}
}
else
@@ -742,9 +758,11 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl)
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_update_ruv: "
"unable to initialize RUV for replica %s\n",
slapi_sdn_get_dn(r->repl_root));
+ rc = RUV_NOTFOUND;
}
PR_Unlock(r->repl_lock);
}
+ return rc;
}
/*
@@ -2462,7 +2480,11 @@ replica_update_state (time_t when, void *arg)
{
/* EY: the consumer needs to flush ruv to disk. */
PR_Unlock(r->repl_lock);
- replica_write_ruv(r);
+ if (replica_write_ruv(r)) {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "_replica_update_state: failed write RUV for %s\n",
+ slapi_sdn_get_dn (r->repl_root));
+ }
goto done;
}
@@ -2533,7 +2555,11 @@ replica_update_state (time_t when, void *arg)
}
/* update RUV - performs its own locking */
- replica_write_ruv (r);
+ if (replica_write_ruv(r)) {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "_replica_update_state: failed write RUV for %s\n",
+ slapi_sdn_get_dn (r->repl_root));
+ }
/* since this is the only place this value is changed and we are
guaranteed that only one thread enters the function, its ok
@@ -2549,10 +2575,10 @@ done:
object_release (replica_object);
}
-void
+int
replica_write_ruv (Replica *r)
{
- int rc;
+ int rc = LDAP_SUCCESS;
Slapi_Mod smod;
Slapi_Mod smod_last_modified;
LDAPMod *mods [3];
@@ -2565,7 +2591,7 @@ replica_write_ruv (Replica *r)
if (!r->repl_ruv_dirty)
{
PR_Unlock(r->repl_lock);
- return;
+ return rc;
}
PR_ASSERT (r->repl_ruv);
@@ -2622,6 +2648,8 @@ replica_write_ruv (Replica *r)
slapi_mod_done (&smod);
slapi_mod_done (&smod_last_modified);
slapi_pblock_destroy (pb);
+
+ return rc;
}
@@ -2642,6 +2670,7 @@ replica_ruv_smods_for_op( Slapi_PBlock *pb, char **uniqueid, Slapi_Mods **smods
Slapi_Mod smod_last_modified;
Slapi_Operation *op;
Slapi_Entry *target_entry = NULL;
+ int rc = 0;
slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &target_entry);
if (target_entry && is_ruv_tombstone_entry(target_entry)) {
@@ -2680,19 +2709,32 @@ replica_ruv_smods_for_op( Slapi_PBlock *pb, char **uniqueid, Slapi_Mods **smods
object_release (ruv_obj);
object_release (replica_obj);
- ruv_set_max_csn( ruv_copy, opcsn, NULL );
-
- ruv_to_smod( ruv_copy, &smod );
- ruv_last_modified_to_smod( ruv_copy, &smod_last_modified );
+ rc = ruv_set_max_csn_ext( ruv_copy, opcsn, NULL, PR_TRUE );
+ if (rc == RUV_COVERS_CSN) { /* change would "revert" RUV - ignored */
+ rc = 0; /* tell caller to ignore */
+ } else if (rc == RUV_SUCCESS) {
+ rc = 1; /* tell caller success */
+ } else { /* error */
+ rc = -1; /* tell caller error */
+ }
+ if (rc == 1) {
+ ruv_to_smod( ruv_copy, &smod );
+ ruv_last_modified_to_smod( ruv_copy, &smod_last_modified );
+ }
ruv_destroy( &ruv_copy );
- *smods = slapi_mods_new();
- slapi_mods_add_smod(*smods, &smod);
- slapi_mods_add_smod(*smods, &smod_last_modified);
- *uniqueid = slapi_ch_strdup( RUV_STORAGE_ENTRY_UNIQUEID );
+ if (rc == 1) {
+ *smods = slapi_mods_new();
+ slapi_mods_add_smod(*smods, &smod);
+ slapi_mods_add_smod(*smods, &smod_last_modified);
+ *uniqueid = slapi_ch_strdup( RUV_STORAGE_ENTRY_UNIQUEID );
+ } else {
+ *smods = NULL;
+ *uniqueid = NULL;
+ }
- return (1);
+ return rc;
}
@@ -3437,7 +3479,9 @@ replica_strip_cleaned_rids(Replica *r)
while(rid[i] != 0){
ruv_delete_replica(ruv, rid[i]);
replica_set_ruv_dirty(r);
- replica_write_ruv(r);
+ if (replica_write_ruv(r)) {
+ slapi_log_error (SLAPI_LOG_REPL, "replica_strip_cleaned_rids", "failed to write RUV\n");
+ }
i++;
}
object_release(RUVObj);
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index 1aa69f0..b6a2d72 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -1304,7 +1304,9 @@ replica_execute_cleanruv_task (Object *r, ReplicaId rid, char *returntext /* not
}
rc = ruv_delete_replica(local_ruv, rid);
replica_set_ruv_dirty(replica);
- replica_write_ruv(replica);
+ if (replica_write_ruv(replica)) {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanruv_task: could not write RUV\n");
+ }
object_release(RUVObj);
/* Update Mapping Tree to reflect RUV changes */
diff --git a/ldap/servers/plugins/replication/repl5_ruv.c b/ldap/servers/plugins/replication/repl5_ruv.c
index d882326..b68223b 100644
--- a/ldap/servers/plugins/replication/repl5_ruv.c
+++ b/ldap/servers/plugins/replication/repl5_ruv.c
@@ -677,26 +677,34 @@ set_min_csn_nolock(RUV *ruv, const CSN *min_csn, const char *replica_purl)
}
static int
-set_max_csn_nolock(RUV *ruv, const CSN *max_csn, const char *replica_purl)
+set_max_csn_nolock_ext(RUV *ruv, const CSN *max_csn, const char *replica_purl, PRBool must_be_greater)
{
- int return_value;
+ int return_value = RUV_SUCCESS;
ReplicaId rid = csn_get_replicaid (max_csn);
RUVElement *replica = ruvGetReplica (ruv, rid);
- if (NULL == replica)
- {
- replica = ruvAddReplica (ruv, max_csn, replica_purl);
- if (replica)
- return_value = RUV_SUCCESS;
- else
- return_value = RUV_MEMORY_ERROR;
- }
- else
- {
- if (replica_purl && replica->replica_purl == NULL)
- replica->replica_purl = slapi_ch_strdup (replica_purl);
- csn_free(&replica->csn);
- replica->csn = csn_dup(max_csn);
- replica->last_modified = current_time();
+ if (NULL == replica) {
+ replica = ruvAddReplica (ruv, max_csn, replica_purl);
+ if (replica)
+ return_value = RUV_SUCCESS;
+ else
+ return_value = RUV_MEMORY_ERROR;
+ } else {
+ if (replica_purl && replica->replica_purl == NULL)
+ replica->replica_purl = slapi_ch_strdup (replica_purl);
+ if (!must_be_greater || (csn_compare(replica->csn, max_csn) < 0)) {
+ csn_free(&replica->csn);
+ replica->csn = csn_dup(max_csn);
+ replica->last_modified = current_time();
+ } else {
+ char csn1[CSN_STRSIZE+1];
+ char csn2[CSN_STRSIZE+1];
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "set_max_csn_nolock_ext: new CSN [%s] for replica ID [%d] "
+ "is less than the existing max CSN [%s] - ignoring\n",
+ csn_as_string(max_csn, PR_FALSE, csn1), rid,
+ csn_as_string(replica->csn, PR_FALSE, csn2));
+ return_value = RUV_COVERS_CSN;
+ }
return_value = RUV_SUCCESS;
}
return return_value;
@@ -716,9 +724,15 @@ ruv_set_min_csn(RUV *ruv, const CSN *min_csn, const char *replica_purl)
int
ruv_set_max_csn(RUV *ruv, const CSN *max_csn, const char *replica_purl)
{
+ return ruv_set_max_csn_ext(ruv, max_csn, replica_purl, PR_FALSE);
+}
+
+int
+ruv_set_max_csn_ext(RUV *ruv, const CSN *max_csn, const char *replica_purl, PRBool must_be_greater)
+{
int return_value;
slapi_rwlock_wrlock (ruv->lock);
- return_value = set_max_csn_nolock(ruv, max_csn, replica_purl);
+ return_value = set_max_csn_nolock_ext(ruv, max_csn, replica_purl, must_be_greater);
slapi_rwlock_unlock (ruv->lock);
return return_value;
}
@@ -1742,8 +1756,9 @@ int ruv_update_ruv (RUV *ruv, const CSN *csn, const char *replica_purl, PRBool i
* generated by this replica, we need to set the first_csn as the min csn in the
* ruv */
set_min_csn_nolock(ruv, first_csn, replica_purl);
- }
- set_max_csn_nolock(ruv, max_csn, replica_purl);
+ }
+ /* only update the max_csn in the RUV if it is greater than the existing one */
+ rc = set_max_csn_nolock_ext(ruv, max_csn, replica_purl, PR_TRUE /* must be greater */);
/* It is possible that first_csn points to max_csn.
We need to free it once */
if (max_csn != first_csn) {
diff --git a/ldap/servers/plugins/replication/repl5_ruv.h b/ldap/servers/plugins/replication/repl5_ruv.h
index 4d84662..a5a0c19 100644
--- a/ldap/servers/plugins/replication/repl5_ruv.h
+++ b/ldap/servers/plugins/replication/repl5_ruv.h
@@ -113,6 +113,7 @@ int ruv_get_smallest_csn_for_replica(const RUV *ruv, ReplicaId rid, CSN **csn);
int ruv_set_csns(RUV *ruv, const CSN *csn, const char *replica_purl);
int ruv_set_csns_keep_smallest(RUV *ruv, const CSN *csn);
int ruv_set_max_csn(RUV *ruv, const CSN *max_csn, const char *replica_purl);
+int ruv_set_max_csn_ext(RUV *ruv, const CSN *max_csn, const char *replica_purl, PRBool must_be_greater);
int ruv_set_min_csn(RUV *ruv, const CSN *min_csn, const char *replica_purl);
const char *ruv_get_purl_for_replica(const RUV *ruv, ReplicaId rid);
char *ruv_get_replica_generation (const RUV *ruv);
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c
index c7d1f62..0cd9432 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c
@@ -344,6 +344,11 @@ ldbm_back_add( Slapi_PBlock *pb )
goto error_return;
}
}
+ if (ruv_c_init) {
+ /* reset the ruv txn stuff */
+ modify_term(&ruv_c, be);
+ ruv_c_init = 0;
+ }
/* We're re-trying */
LDAPDebug0Args(LDAP_DEBUG_BACKLDBM, "Add Retrying Transaction\n");
@@ -759,19 +764,6 @@ ldbm_back_add( Slapi_PBlock *pb )
parententry = NULL;
}
- if (!is_ruv && !is_fixup_operation && !NO_RUV_UPDATE(li)) {
- ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
- if (-1 == ruv_c_init) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm_back_add: ldbm_txn_ruv_modify_context "
- "failed to construct RUV modify context\n",
- 0, 0, 0);
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- retval = 0;
- goto error_return;
- }
- }
-
if ( (originalentry = backentry_dup(addingentry )) == NULL ) {
ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
@@ -952,6 +944,19 @@ ldbm_back_add( Slapi_PBlock *pb )
}
}
+ if (!is_ruv && !is_fixup_operation && !NO_RUV_UPDATE(li)) {
+ ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
+ if (-1 == ruv_c_init) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ldbm_back_add: ldbm_txn_ruv_modify_context "
+ "failed to construct RUV modify context\n",
+ 0, 0, 0);
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ retval = 0;
+ goto error_return;
+ }
+ }
+
if (ruv_c_init) {
retval = modify_update_all( be, pb, &ruv_c, &txn );
if (DB_LOCK_DEADLOCK == retval) {
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
index 0478a12..61af3a6 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
@@ -235,6 +235,12 @@ ldbm_back_delete( Slapi_PBlock *pb )
e_in_cache = 1;
}
+ if (ruv_c_init) {
+ /* reset the ruv txn stuff */
+ modify_term(&ruv_c, be);
+ ruv_c_init = 0;
+ }
+
/* We're re-trying */
LDAPDebug0Args(LDAP_DEBUG_BACKLDBM,
"Delete Retrying Transaction\n");
@@ -550,19 +556,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
goto error_return;
}
}
-
- if (!is_ruv && !is_fixup_operation && !delete_tombstone_entry && !NO_RUV_UPDATE(li)) {
- ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
- if (-1 == ruv_c_init) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm_back_delete: ldbm_txn_ruv_modify_context "
- "failed to construct RUV modify context\n",
- 0, 0, 0);
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- retval = 0;
- goto error_return;
- }
- }
} /* if (0 == retry_count) just once */
else {
/* call the transaction pre delete plugins not just once
@@ -1028,6 +1021,19 @@ ldbm_back_delete( Slapi_PBlock *pb )
}
}
+ if (!is_ruv && !is_fixup_operation && !delete_tombstone_entry && !NO_RUV_UPDATE(li)) {
+ ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
+ if (-1 == ruv_c_init) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ldbm_back_delete: ldbm_txn_ruv_modify_context "
+ "failed to construct RUV modify context\n",
+ 0, 0, 0);
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ retval = 0;
+ goto error_return;
+ }
+ }
+
if (ruv_c_init) {
retval = modify_update_all( be, pb, &ruv_c, &txn );
if (DB_LOCK_DEADLOCK == retval) {
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
index c00194b..d2302fe 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
@@ -445,6 +445,12 @@ ldbm_back_modify( Slapi_PBlock *pb )
goto error_return;
}
+ if (ruv_c_init) {
+ /* reset the ruv txn stuff */
+ modify_term(&ruv_c, be);
+ ruv_c_init = 0;
+ }
+
LDAPDebug0Args(LDAP_DEBUG_BACKLDBM,
"Modify Retrying Transaction\n");
#ifndef LDBM_NO_BACKOFF_DELAY
@@ -560,19 +566,6 @@ ldbm_back_modify( Slapi_PBlock *pb )
goto error_return;
}
- if (!is_ruv && !is_fixup_operation && !NO_RUV_UPDATE(li)) {
- ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
- if (-1 == ruv_c_init) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm_back_modify: ldbm_txn_ruv_modify_context "
- "failed to construct RUV modify context\n",
- 0, 0, 0);
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- retval = 0;
- goto error_return;
- }
- }
-
/*
* Grab a copy of the mods and the entry in case the be_txn_preop changes
* the them. If we have a failure, then we need to reset the mods to their
@@ -679,6 +672,19 @@ ldbm_back_modify( Slapi_PBlock *pb )
}
+ if (!is_ruv && !is_fixup_operation && !NO_RUV_UPDATE(li)) {
+ ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
+ if (-1 == ruv_c_init) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ldbm_back_modify: ldbm_txn_ruv_modify_context "
+ "failed to construct RUV modify context\n",
+ 0, 0, 0);
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ retval = 0;
+ goto error_return;
+ }
+ }
+
if (ruv_c_init) {
retval = modify_update_all( be, pb, &ruv_c, &txn );
if (DB_LOCK_DEADLOCK == retval) {
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
index fe53554..416b928 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
@@ -309,6 +309,11 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
goto error_return;
}
+ if (ruv_c_init) {
+ /* reset the ruv txn stuff */
+ modify_term(&ruv_c, be);
+ ruv_c_init = 0;
+ }
/* We're re-trying */
LDAPDebug0Args(LDAP_DEBUG_BACKLDBM,
"Modrdn Retrying Transaction\n");
@@ -846,19 +851,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
/* JCM - A subtree move could break ACIs, static groups, and dynamic groups. */
}
- if (!is_ruv && !is_fixup_operation && !NO_RUV_UPDATE(li)) {
- ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
- if (-1 == ruv_c_init) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm_back_modrdn: ldbm_txn_ruv_modify_context "
- "failed to construct RUV modify context\n",
- 0, 0, 0);
- ldap_result_code = LDAP_OPERATIONS_ERROR;
- retval = 0;
- goto error_return;
- }
- }
-
/*
* make copies of the originals, no need to copy the mods because
* we have already copied them
@@ -1065,6 +1057,19 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
goto error_return;
}
+ if (!is_ruv && !is_fixup_operation && !NO_RUV_UPDATE(li)) {
+ ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
+ if (-1 == ruv_c_init) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ldbm_back_modrdn: ldbm_txn_ruv_modify_context "
+ "failed to construct RUV modify context\n",
+ 0, 0, 0);
+ ldap_result_code = LDAP_OPERATIONS_ERROR;
+ retval = 0;
+ goto error_return;
+ }
+ }
+
if (ruv_c_init) {
retval = modify_update_all( be, pb, &ruv_c, &txn );
if (DB_LOCK_DEADLOCK == retval) {
diff --git a/ldap/servers/slapd/back-ldbm/misc.c b/ldap/servers/slapd/back-ldbm/misc.c
index 87262c5..00d48b3 100644
--- a/ldap/servers/slapd/back-ldbm/misc.c
+++ b/ldap/servers/slapd/back-ldbm/misc.c
@@ -426,6 +426,7 @@ ldbm_txn_ruv_modify_context( Slapi_PBlock *pb, modify_context *mc )
/* Either something went wrong when the RUV callback tried to assemble
* the updates for us, or there were no updates because the op doesn't
* target a replica. */
+ /* or, the CSN is already covered by the RUV */
if (1 != rc || NULL == smods || NULL == uniqueid) {
return (rc);
}
10 years, 10 months
Branch '389-ds-base-1.2.11' - ldap/servers
by Richard Allen Megginson
ldap/servers/plugins/replication/repl5.h | 4
ldap/servers/plugins/replication/repl5_plugins.c | 29 ++++-
ldap/servers/plugins/replication/repl5_replica.c | 84 ++++++++++++----
ldap/servers/plugins/replication/repl5_replica_config.c | 4
ldap/servers/plugins/replication/repl5_ruv.c | 55 ++++++----
ldap/servers/plugins/replication/repl5_ruv.h | 1
ldap/servers/slapd/back-ldbm/ldbm_add.c | 31 +++--
ldap/servers/slapd/back-ldbm/ldbm_delete.c | 32 +++---
ldap/servers/slapd/back-ldbm/ldbm_modify.c | 32 +++---
ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 31 +++--
ldap/servers/slapd/back-ldbm/misc.c | 1
11 files changed, 205 insertions(+), 99 deletions(-)
New commits:
commit 42abece92028193530296b5d96a6cb5261d9aa61
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Tue Jul 9 11:38:39 2013 -0600
Ticket #47392 - ldbm errors when adding/modifying/deleting entries
https://fedorahosted.org/389/ticket/47392
Reviewed by: lkrispenz (Thanks!)
Branch: 389-ds-base-1.2.11
Fix Description: The problem is caused by cache consistency issues with the
RUV entry. Before the txn starts, we grab a pointer to the RUV entry in
the cache. When DNA (or any betxnpreop plugin) updates the database, it
will also grab a pointer to the cached RUV entry and modify it, out from
under the parent txn. This can also cause the max CSN in the RUV to go
backwards - the nested txn will have a later CSN which will be
overwritten by the earlier CSN from the parent txn.
The fix is to move the ldbm_ruv_txn code inside the transaction loop after
the betxnpreop plugins have been run. Also have to add modify_term inside
the retry logic to cancel the modify ruv txn stuff in order to retry.
The other part of the fix is to tell the code that updates the max CSN
in the RUV to skip changes that would cause the RUV to go backwards,
and return a code to the caller that tells the caller that the CSN is
already covered. The code that updates the RUV for the txn will skip
the modify operations in that case.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
(cherry picked from commit 9bf5ac83289dcadc922a628c652aebabc4725231)
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index bd582bc..780b198 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -538,7 +538,7 @@ void replica_replace_flags (Replica *r, PRUint32 flags);
void replica_dump(Replica *r);
void replica_set_enabled (Replica *r, PRBool enable);
Object *replica_get_replica_from_dn (const Slapi_DN *dn);
-void replica_update_ruv(Replica *replica, const CSN *csn, const char *replica_purl);
+int replica_update_ruv(Replica *replica, const CSN *csn, const char *replica_purl);
Object *replica_get_replica_for_op (Slapi_PBlock *pb);
/* the functions below manipulate replica hash */
int replica_init_name_hash ();
@@ -570,7 +570,7 @@ void replica_set_purge_delay (Replica *r, PRUint32 purge_delay);
void replica_set_tombstone_reap_interval (Replica *r, long interval);
void replica_update_ruv_consumer (Replica *r, RUV *supplier_ruv);
void replica_set_ruv_dirty (Replica *r);
-void replica_write_ruv (Replica *r);
+int replica_write_ruv (Replica *r);
char *replica_get_dn(Replica *r);
void replica_check_for_tasks(Replica*r, Slapi_Entry *e);
diff --git a/ldap/servers/plugins/replication/repl5_plugins.c b/ldap/servers/plugins/replication/repl5_plugins.c
index e3c3083..7aa2e2c 100644
--- a/ldap/servers/plugins/replication/repl5_plugins.c
+++ b/ldap/servers/plugins/replication/repl5_plugins.c
@@ -932,14 +932,15 @@ copy_operation_parameters(Slapi_PBlock *pb)
* locally-processed update. This is called for both replicated
* and non-replicated operations.
*/
-static void
+static int
update_ruv_component(Replica *replica, CSN *opcsn, Slapi_PBlock *pb)
{
PRBool legacy;
char *purl;
+ int rc = RUV_NOTFOUND;
if (!replica || !opcsn)
- return;
+ return rc;
/* Replica configured, so update its ruv */
legacy = replica_is_legacy_consumer (replica);
@@ -948,12 +949,13 @@ update_ruv_component(Replica *replica, CSN *opcsn, Slapi_PBlock *pb)
else
purl = (char*)replica_get_purl_for_op (replica, pb, opcsn);
- replica_update_ruv(replica, opcsn, purl);
+ rc = replica_update_ruv(replica, opcsn, purl);
if (legacy)
{
slapi_ch_free ((void**)&purl);
}
+ return rc;
}
/*
@@ -1115,11 +1117,30 @@ write_changelog_and_ruv (Slapi_PBlock *pb)
just read from the changelog in either the supplier or consumer ruv
*/
if (0 == return_value) {
+ char csn_str[CSN_STRSIZE];
CSN *opcsn;
+ int rc;
slapi_pblock_get( pb, SLAPI_OPERATION, &op );
opcsn = operation_get_csn(op);
- update_ruv_component(r, opcsn, pb);
+ rc = update_ruv_component(r, opcsn, pb);
+ if (RUV_COVERS_CSN == rc) {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "write_changelog_and_ruv: RUV already covers csn for "
+ "%s (uniqid: %s, optype: %lu) csn %s\n",
+ REPL_GET_DN(&op_params->target_address),
+ op_params->target_address.uniqueid,
+ op_params->operation_type,
+ csn_as_string(op_params->csn, PR_FALSE, csn_str));
+ } else if (rc != RUV_SUCCESS) {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+ "write_changelog_and_ruv: failed to update RUV for "
+ "%s (uniqid: %s, optype: %lu) to changelog csn %s\n",
+ REPL_GET_DN(&op_params->target_address),
+ op_params->target_address.uniqueid,
+ op_params->operation_type,
+ csn_as_string(op_params->csn, PR_FALSE, csn_str));
+ }
}
object_release (repl_obj);
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
index b3df831..8187be9 100644
--- a/ldap/servers/plugins/replication/repl5_replica.c
+++ b/ldap/servers/plugins/replication/repl5_replica.c
@@ -657,10 +657,11 @@ replica_set_ruv (Replica *r, RUV *ruv)
* inbound replication session operation, and needs to update its
* local RUV.
*/
-void
+int
replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl)
{
char csn_str[CSN_STRSIZE];
+ int rc = RUV_SUCCESS;
PR_ASSERT(NULL != r);
PR_ASSERT(NULL != updated_csn);
@@ -673,11 +674,13 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl)
{
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_update_ruv: replica "
"is NULL\n");
+ rc = RUV_BAD_DATA;
}
else if (NULL == updated_csn)
{
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_update_ruv: csn "
"is NULL when updating replica %s\n", slapi_sdn_get_dn(r->repl_root));
+ rc = RUV_BAD_DATA;
}
else
{
@@ -710,8 +713,17 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl)
}
}
/* Update max csn for local and remote replicas */
- if (ruv_update_ruv (ruv, updated_csn, replica_purl, rid == r->repl_rid)
- != RUV_SUCCESS)
+ rc = ruv_update_ruv (ruv, updated_csn, replica_purl, rid == r->repl_rid);
+ if (RUV_COVERS_CSN == rc)
+ {
+ slapi_log_error(SLAPI_LOG_REPL,
+ repl_plugin_name, "replica_update_ruv: RUV "
+ "for replica %s already covers max_csn = %s\n",
+ slapi_sdn_get_dn(r->repl_root),
+ csn_as_string(updated_csn, PR_FALSE, csn_str));
+ /* RUV is not dirty - no write needed */
+ }
+ else if (RUV_SUCCESS != rc)
{
slapi_log_error(SLAPI_LOG_FATAL,
repl_plugin_name, "replica_update_ruv: unable "
@@ -719,14 +731,18 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl)
slapi_sdn_get_dn(r->repl_root),
csn_as_string(updated_csn, PR_FALSE, csn_str));
}
-
- r->repl_ruv_dirty = PR_TRUE;
+ else
+ {
+ /* RUV updated - mark as dirty */
+ r->repl_ruv_dirty = PR_TRUE;
+ }
}
else
{
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
"replica_update_ruv: unable to get RUV object for replica "
"%s\n", slapi_sdn_get_dn(r->repl_root));
+ rc = RUV_NOTFOUND;
}
}
else
@@ -734,9 +750,11 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl)
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_update_ruv: "
"unable to initialize RUV for replica %s\n",
slapi_sdn_get_dn(r->repl_root));
+ rc = RUV_NOTFOUND;
}
PR_Unlock(r->repl_lock);
}
+ return rc;
}
/*
@@ -2400,7 +2418,11 @@ _replica_update_state (time_t when, void *arg)
{
/* EY: the consumer needs to flush ruv to disk. */
PR_Unlock(r->repl_lock);
- replica_write_ruv(r);
+ if (replica_write_ruv(r)) {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "_replica_update_state: failed write RUV for %s\n",
+ slapi_sdn_get_dn (r->repl_root));
+ }
goto done;
}
@@ -2471,7 +2493,11 @@ _replica_update_state (time_t when, void *arg)
}
/* update RUV - performs its own locking */
- replica_write_ruv (r);
+ if (replica_write_ruv(r)) {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "_replica_update_state: failed write RUV for %s\n",
+ slapi_sdn_get_dn (r->repl_root));
+ }
/* since this is the only place this value is changed and we are
guaranteed that only one thread enters the function, its ok
@@ -2487,10 +2513,10 @@ done:
object_release (replica_object);
}
-void
+int
replica_write_ruv (Replica *r)
{
- int rc;
+ int rc = LDAP_SUCCESS;
Slapi_Mod smod;
Slapi_Mod smod_last_modified;
LDAPMod *mods [3];
@@ -2503,7 +2529,7 @@ replica_write_ruv (Replica *r)
if (!r->repl_ruv_dirty)
{
PR_Unlock(r->repl_lock);
- return;
+ return rc;
}
PR_ASSERT (r->repl_ruv);
@@ -2560,6 +2586,8 @@ replica_write_ruv (Replica *r)
slapi_mod_done (&smod);
slapi_mod_done (&smod_last_modified);
slapi_pblock_destroy (pb);
+
+ return rc;
}
@@ -2580,6 +2608,7 @@ replica_ruv_smods_for_op( Slapi_PBlock *pb, char **uniqueid, Slapi_Mods **smods
Slapi_Mod smod_last_modified;
Slapi_Operation *op;
Slapi_Entry *target_entry = NULL;
+ int rc = 0;
slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &target_entry);
if (target_entry && is_ruv_tombstone_entry(target_entry)) {
@@ -2618,19 +2647,32 @@ replica_ruv_smods_for_op( Slapi_PBlock *pb, char **uniqueid, Slapi_Mods **smods
object_release (ruv_obj);
object_release (replica_obj);
- ruv_set_max_csn( ruv_copy, opcsn, NULL );
-
- ruv_to_smod( ruv_copy, &smod );
- ruv_last_modified_to_smod( ruv_copy, &smod_last_modified );
+ rc = ruv_set_max_csn_ext( ruv_copy, opcsn, NULL, PR_TRUE );
+ if (rc == RUV_COVERS_CSN) { /* change would "revert" RUV - ignored */
+ rc = 0; /* tell caller to ignore */
+ } else if (rc == RUV_SUCCESS) {
+ rc = 1; /* tell caller success */
+ } else { /* error */
+ rc = -1; /* tell caller error */
+ }
+ if (rc == 1) {
+ ruv_to_smod( ruv_copy, &smod );
+ ruv_last_modified_to_smod( ruv_copy, &smod_last_modified );
+ }
ruv_destroy( &ruv_copy );
- *smods = slapi_mods_new();
- slapi_mods_add_smod(*smods, &smod);
- slapi_mods_add_smod(*smods, &smod_last_modified);
- *uniqueid = slapi_ch_strdup( RUV_STORAGE_ENTRY_UNIQUEID );
+ if (rc == 1) {
+ *smods = slapi_mods_new();
+ slapi_mods_add_smod(*smods, &smod);
+ slapi_mods_add_smod(*smods, &smod_last_modified);
+ *uniqueid = slapi_ch_strdup( RUV_STORAGE_ENTRY_UNIQUEID );
+ } else {
+ *smods = NULL;
+ *uniqueid = NULL;
+ }
- return (1);
+ return rc;
}
@@ -3375,7 +3417,9 @@ replica_strip_cleaned_rids(Replica *r)
while(rid[i] != 0){
ruv_delete_replica(ruv, rid[i]);
replica_set_ruv_dirty(r);
- replica_write_ruv(r);
+ if (replica_write_ruv(r)) {
+ slapi_log_error (SLAPI_LOG_REPL, "replica_strip_cleaned_rids", "failed to write RUV\n");
+ }
i++;
}
object_release(RUVObj);
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index 7422976..c2ad504 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -1200,7 +1200,9 @@ replica_execute_cleanruv_task (Object *r, ReplicaId rid, char *returntext /* not
}
rc = ruv_delete_replica(local_ruv, rid);
replica_set_ruv_dirty(replica);
- replica_write_ruv(replica);
+ if (replica_write_ruv(replica)) {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanruv_task: could not write RUV\n");
+ }
object_release(RUVObj);
/* Update Mapping Tree to reflect RUV changes */
diff --git a/ldap/servers/plugins/replication/repl5_ruv.c b/ldap/servers/plugins/replication/repl5_ruv.c
index 8fbd89c..2808c58 100644
--- a/ldap/servers/plugins/replication/repl5_ruv.c
+++ b/ldap/servers/plugins/replication/repl5_ruv.c
@@ -665,26 +665,34 @@ set_min_csn_nolock(RUV *ruv, const CSN *min_csn, const char *replica_purl)
}
static int
-set_max_csn_nolock(RUV *ruv, const CSN *max_csn, const char *replica_purl)
+set_max_csn_nolock_ext(RUV *ruv, const CSN *max_csn, const char *replica_purl, PRBool must_be_greater)
{
- int return_value;
+ int return_value = RUV_SUCCESS;
ReplicaId rid = csn_get_replicaid (max_csn);
RUVElement *replica = ruvGetReplica (ruv, rid);
- if (NULL == replica)
- {
- replica = ruvAddReplica (ruv, max_csn, replica_purl);
- if (replica)
- return_value = RUV_SUCCESS;
- else
- return_value = RUV_MEMORY_ERROR;
- }
- else
- {
- if (replica_purl && replica->replica_purl == NULL)
- replica->replica_purl = slapi_ch_strdup (replica_purl);
- csn_free(&replica->csn);
- replica->csn = csn_dup(max_csn);
- replica->last_modified = current_time();
+ if (NULL == replica) {
+ replica = ruvAddReplica (ruv, max_csn, replica_purl);
+ if (replica)
+ return_value = RUV_SUCCESS;
+ else
+ return_value = RUV_MEMORY_ERROR;
+ } else {
+ if (replica_purl && replica->replica_purl == NULL)
+ replica->replica_purl = slapi_ch_strdup (replica_purl);
+ if (!must_be_greater || (csn_compare(replica->csn, max_csn) < 0)) {
+ csn_free(&replica->csn);
+ replica->csn = csn_dup(max_csn);
+ replica->last_modified = current_time();
+ } else {
+ char csn1[CSN_STRSIZE+1];
+ char csn2[CSN_STRSIZE+1];
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "set_max_csn_nolock_ext: new CSN [%s] for replica ID [%d] "
+ "is less than the existing max CSN [%s] - ignoring\n",
+ csn_as_string(max_csn, PR_FALSE, csn1), rid,
+ csn_as_string(replica->csn, PR_FALSE, csn2));
+ return_value = RUV_COVERS_CSN;
+ }
return_value = RUV_SUCCESS;
}
return return_value;
@@ -704,9 +712,15 @@ ruv_set_min_csn(RUV *ruv, const CSN *min_csn, const char *replica_purl)
int
ruv_set_max_csn(RUV *ruv, const CSN *max_csn, const char *replica_purl)
{
+ return ruv_set_max_csn_ext(ruv, max_csn, replica_purl, PR_FALSE);
+}
+
+int
+ruv_set_max_csn_ext(RUV *ruv, const CSN *max_csn, const char *replica_purl, PRBool must_be_greater)
+{
int return_value;
slapi_rwlock_wrlock (ruv->lock);
- return_value = set_max_csn_nolock(ruv, max_csn, replica_purl);
+ return_value = set_max_csn_nolock_ext(ruv, max_csn, replica_purl, must_be_greater);
slapi_rwlock_unlock (ruv->lock);
return return_value;
}
@@ -1654,8 +1668,9 @@ int ruv_update_ruv (RUV *ruv, const CSN *csn, const char *replica_purl, PRBool i
* generated by this replica, we need to set the first_csn as the min csn in the
* ruv */
set_min_csn_nolock(ruv, first_csn, replica_purl);
- }
- set_max_csn_nolock(ruv, max_csn, replica_purl);
+ }
+ /* only update the max_csn in the RUV if it is greater than the existing one */
+ rc = set_max_csn_nolock_ext(ruv, max_csn, replica_purl, PR_TRUE /* must be greater */);
/* It is possible that first_csn points to max_csn.
We need to free it once */
if (max_csn != first_csn) {
diff --git a/ldap/servers/plugins/replication/repl5_ruv.h b/ldap/servers/plugins/replication/repl5_ruv.h
index 944f5ed..fdc8af2 100644
--- a/ldap/servers/plugins/replication/repl5_ruv.h
+++ b/ldap/servers/plugins/replication/repl5_ruv.h
@@ -108,6 +108,7 @@ int ruv_get_smallest_csn_for_replica(const RUV *ruv, ReplicaId rid, CSN **csn);
int ruv_set_csns(RUV *ruv, const CSN *csn, const char *replica_purl);
int ruv_set_csns_keep_smallest(RUV *ruv, const CSN *csn);
int ruv_set_max_csn(RUV *ruv, const CSN *max_csn, const char *replica_purl);
+int ruv_set_max_csn_ext(RUV *ruv, const CSN *max_csn, const char *replica_purl, PRBool must_be_greater);
int ruv_set_min_csn(RUV *ruv, const CSN *min_csn, const char *replica_purl);
const char *ruv_get_purl_for_replica(const RUV *ruv, ReplicaId rid);
char *ruv_get_replica_generation (const RUV *ruv);
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c
index 78ca565..554822c 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c
@@ -668,19 +668,6 @@ ldbm_back_add( Slapi_PBlock *pb )
parententry = NULL;
}
- if (!is_ruv && !is_fixup_operation) {
- ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
- if (-1 == ruv_c_init) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm_back_add: ldbm_txn_ruv_modify_context "
- "failed to construct RUV modify context\n",
- 0, 0, 0);
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- retval = 0;
- goto error_return;
- }
- }
-
if ( (originalentry = backentry_dup(addingentry )) == NULL ) {
ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
@@ -718,6 +705,11 @@ ldbm_back_add( Slapi_PBlock *pb )
goto error_return;
}
}
+ if (ruv_c_init) {
+ /* reset the ruv txn stuff */
+ modify_term(&ruv_c, be);
+ ruv_c_init = 0;
+ }
/* We're re-trying */
LDAPDebug0Args(LDAP_DEBUG_BACKLDBM, "Add Retrying Transaction\n");
@@ -910,6 +902,19 @@ ldbm_back_add( Slapi_PBlock *pb )
}
}
+ if (!is_ruv && !is_fixup_operation) {
+ ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
+ if (-1 == ruv_c_init) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ldbm_back_add: ldbm_txn_ruv_modify_context "
+ "failed to construct RUV modify context\n",
+ 0, 0, 0);
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ retval = 0;
+ goto error_return;
+ }
+ }
+
if (ruv_c_init) {
retval = modify_update_all( be, pb, &ruv_c, &txn );
if (DB_LOCK_DEADLOCK == retval) {
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
index d80c54e..3cf58f4 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
@@ -451,19 +451,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
}
}
- if (!is_ruv && !is_fixup_operation && !delete_tombstone_entry) {
- ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
- if (-1 == ruv_c_init) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm_back_delete: ldbm_txn_ruv_modify_context "
- "failed to construct RUV modify context\n",
- 0, 0, 0);
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- retval = 0;
- goto error_return;
- }
- }
-
/*
* So, we believe that no code up till here actually added anything
* to the persistent store. From now on, we're transacted
@@ -511,6 +498,12 @@ ldbm_back_delete( Slapi_PBlock *pb )
e_in_cache = 1;
}
+ if (ruv_c_init) {
+ /* reset the ruv txn stuff */
+ modify_term(&ruv_c, be);
+ ruv_c_init = 0;
+ }
+
/* We're re-trying */
LDAPDebug0Args(LDAP_DEBUG_BACKLDBM,
"Delete Retrying Transaction\n");
@@ -991,6 +984,19 @@ ldbm_back_delete( Slapi_PBlock *pb )
}
}
+ if (!is_ruv && !is_fixup_operation && !delete_tombstone_entry) {
+ ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
+ if (-1 == ruv_c_init) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ldbm_back_delete: ldbm_txn_ruv_modify_context "
+ "failed to construct RUV modify context\n",
+ 0, 0, 0);
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ retval = 0;
+ goto error_return;
+ }
+ }
+
if (ruv_c_init) {
retval = modify_update_all( be, pb, &ruv_c, &txn );
if (DB_LOCK_DEADLOCK == retval) {
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
index 66b8ab8..32510ab 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
@@ -476,19 +476,6 @@ ldbm_back_modify( Slapi_PBlock *pb )
goto error_return;
}
- if (!is_ruv && !is_fixup_operation) {
- ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
- if (-1 == ruv_c_init) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm_back_modify: ldbm_txn_ruv_modify_context "
- "failed to construct RUV modify context\n",
- 0, 0, 0);
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- retval = 0;
- goto error_return;
- }
- }
-
/*
* Grab a copy of the mods and the entry in case the be_txn_preop changes
* the them. If we have a failure, then we need to reset the mods to their
@@ -526,6 +513,12 @@ ldbm_back_modify( Slapi_PBlock *pb )
goto error_return;
}
+ if (ruv_c_init) {
+ /* reset the ruv txn stuff */
+ modify_term(&ruv_c, be);
+ ruv_c_init = 0;
+ }
+
LDAPDebug0Args(LDAP_DEBUG_BACKLDBM,
"Modify Retrying Transaction\n");
#ifndef LDBM_NO_BACKOFF_DELAY
@@ -638,6 +631,19 @@ ldbm_back_modify( Slapi_PBlock *pb )
}
+ if (!is_ruv && !is_fixup_operation) {
+ ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
+ if (-1 == ruv_c_init) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ldbm_back_modify: ldbm_txn_ruv_modify_context "
+ "failed to construct RUV modify context\n",
+ 0, 0, 0);
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ retval = 0;
+ goto error_return;
+ }
+ }
+
if (ruv_c_init) {
retval = modify_update_all( be, pb, &ruv_c, &txn );
if (DB_LOCK_DEADLOCK == retval) {
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
index 13514fb..c539463 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
@@ -719,19 +719,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
/* JCM - A subtree move could break ACIs, static groups, and dynamic groups. */
}
- if (!is_ruv && !is_fixup_operation) {
- ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
- if (-1 == ruv_c_init) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm_back_modrdn: ldbm_txn_ruv_modify_context "
- "failed to construct RUV modify context\n",
- 0, 0, 0);
- ldap_result_code = LDAP_OPERATIONS_ERROR;
- retval = 0;
- goto error_return;
- }
- }
-
/*
* make copies of the originals, no need to copy the mods because
* we have already copied them
@@ -833,6 +820,11 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
goto error_return;
}
+ if (ruv_c_init) {
+ /* reset the ruv txn stuff */
+ modify_term(&ruv_c, be);
+ ruv_c_init = 0;
+ }
/* We're re-trying */
LDAPDebug0Args(LDAP_DEBUG_BACKLDBM,
"Modrdn Retrying Transaction\n");
@@ -1035,6 +1027,19 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
goto error_return;
}
+ if (!is_ruv && !is_fixup_operation) {
+ ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
+ if (-1 == ruv_c_init) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ldbm_back_modrdn: ldbm_txn_ruv_modify_context "
+ "failed to construct RUV modify context\n",
+ 0, 0, 0);
+ ldap_result_code = LDAP_OPERATIONS_ERROR;
+ retval = 0;
+ goto error_return;
+ }
+ }
+
if (ruv_c_init) {
retval = modify_update_all( be, pb, &ruv_c, &txn );
if (DB_LOCK_DEADLOCK == retval) {
diff --git a/ldap/servers/slapd/back-ldbm/misc.c b/ldap/servers/slapd/back-ldbm/misc.c
index fd62df9..7a90742 100644
--- a/ldap/servers/slapd/back-ldbm/misc.c
+++ b/ldap/servers/slapd/back-ldbm/misc.c
@@ -420,6 +420,7 @@ ldbm_txn_ruv_modify_context( Slapi_PBlock *pb, modify_context *mc )
/* Either something went wrong when the RUV callback tried to assemble
* the updates for us, or there were no updates because the op doesn't
* target a replica. */
+ /* or, the CSN is already covered by the RUV */
if (1 != rc || NULL == smods || NULL == uniqueid) {
return (rc);
}
10 years, 10 months
Branch '389-ds-base-1.3.1' - ldap/servers
by Richard Allen Megginson
ldap/servers/plugins/replication/repl5.h | 4
ldap/servers/plugins/replication/repl5_plugins.c | 29 ++++-
ldap/servers/plugins/replication/repl5_replica.c | 84 ++++++++++++----
ldap/servers/plugins/replication/repl5_replica_config.c | 4
ldap/servers/plugins/replication/repl5_ruv.c | 55 ++++++----
ldap/servers/plugins/replication/repl5_ruv.h | 1
ldap/servers/slapd/back-ldbm/ldbm_add.c | 31 +++--
ldap/servers/slapd/back-ldbm/ldbm_delete.c | 32 +++---
ldap/servers/slapd/back-ldbm/ldbm_modify.c | 32 +++---
ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 31 +++--
ldap/servers/slapd/back-ldbm/misc.c | 1
11 files changed, 205 insertions(+), 99 deletions(-)
New commits:
commit ff7fb870fb0034857b855d2c9e769cdf00237aad
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Tue Jul 9 11:38:39 2013 -0600
Ticket #47392 - ldbm errors when adding/modifying/deleting entries
https://fedorahosted.org/389/ticket/47392
Reviewed by: lkrispenz (Thanks!)
Branch: 389-ds-base-1.3.1
Fix Description: The problem is caused by cache consistency issues with the
RUV entry. Before the txn starts, we grab a pointer to the RUV entry in
the cache. When DNA (or any betxnpreop plugin) updates the database, it
will also grab a pointer to the cached RUV entry and modify it, out from
under the parent txn. This can also cause the max CSN in the RUV to go
backwards - the nested txn will have a later CSN which will be
overwritten by the earlier CSN from the parent txn.
The fix is to move the ldbm_ruv_txn code inside the transaction loop after
the betxnpreop plugins have been run. Also have to add modify_term inside
the retry logic to cancel the modify ruv txn stuff in order to retry.
The other part of the fix is to tell the code that updates the max CSN
in the RUV to skip changes that would cause the RUV to go backwards,
and return a code to the caller that tells the caller that the CSN is
already covered. The code that updates the RUV for the txn will skip
the modify operations in that case.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index c7639e3..465d072 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -557,7 +557,7 @@ void replica_replace_flags (Replica *r, PRUint32 flags);
void replica_dump(Replica *r);
void replica_set_enabled (Replica *r, PRBool enable);
Object *replica_get_replica_from_dn (const Slapi_DN *dn);
-void replica_update_ruv(Replica *replica, const CSN *csn, const char *replica_purl);
+int replica_update_ruv(Replica *replica, const CSN *csn, const char *replica_purl);
Object *replica_get_replica_for_op (Slapi_PBlock *pb);
/* the functions below manipulate replica hash */
int replica_init_name_hash ();
@@ -590,7 +590,7 @@ void replica_set_purge_delay (Replica *r, PRUint32 purge_delay);
void replica_set_tombstone_reap_interval (Replica *r, long interval);
void replica_update_ruv_consumer (Replica *r, RUV *supplier_ruv);
void replica_set_ruv_dirty (Replica *r);
-void replica_write_ruv (Replica *r);
+int replica_write_ruv (Replica *r);
char *replica_get_dn(Replica *r);
void replica_check_for_tasks(Replica*r, Slapi_Entry *e);
void replica_update_state (time_t when, void *arg);
diff --git a/ldap/servers/plugins/replication/repl5_plugins.c b/ldap/servers/plugins/replication/repl5_plugins.c
index 43c1596..01ac03c 100644
--- a/ldap/servers/plugins/replication/repl5_plugins.c
+++ b/ldap/servers/plugins/replication/repl5_plugins.c
@@ -1081,14 +1081,15 @@ copy_operation_parameters(Slapi_PBlock *pb)
* locally-processed update. This is called for both replicated
* and non-replicated operations.
*/
-static void
+static int
update_ruv_component(Replica *replica, CSN *opcsn, Slapi_PBlock *pb)
{
PRBool legacy;
char *purl;
+ int rc = RUV_NOTFOUND;
if (!replica || !opcsn)
- return;
+ return rc;
/* Replica configured, so update its ruv */
legacy = replica_is_legacy_consumer (replica);
@@ -1097,12 +1098,13 @@ update_ruv_component(Replica *replica, CSN *opcsn, Slapi_PBlock *pb)
else
purl = (char*)replica_get_purl_for_op (replica, pb, opcsn);
- replica_update_ruv(replica, opcsn, purl);
+ rc = replica_update_ruv(replica, opcsn, purl);
if (legacy)
{
slapi_ch_free ((void**)&purl);
}
+ return rc;
}
/*
@@ -1264,11 +1266,30 @@ write_changelog_and_ruv (Slapi_PBlock *pb)
just read from the changelog in either the supplier or consumer ruv
*/
if (0 == return_value) {
+ char csn_str[CSN_STRSIZE];
CSN *opcsn;
+ int rc;
slapi_pblock_get( pb, SLAPI_OPERATION, &op );
opcsn = operation_get_csn(op);
- update_ruv_component(r, opcsn, pb);
+ rc = update_ruv_component(r, opcsn, pb);
+ if (RUV_COVERS_CSN == rc) {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "write_changelog_and_ruv: RUV already covers csn for "
+ "%s (uniqid: %s, optype: %lu) csn %s\n",
+ REPL_GET_DN(&op_params->target_address),
+ op_params->target_address.uniqueid,
+ op_params->operation_type,
+ csn_as_string(op_params->csn, PR_FALSE, csn_str));
+ } else if (rc != RUV_SUCCESS) {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+ "write_changelog_and_ruv: failed to update RUV for "
+ "%s (uniqid: %s, optype: %lu) to changelog csn %s\n",
+ REPL_GET_DN(&op_params->target_address),
+ op_params->target_address.uniqueid,
+ op_params->operation_type,
+ csn_as_string(op_params->csn, PR_FALSE, csn_str));
+ }
}
object_release (repl_obj);
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
index 5a19833..c9df528 100644
--- a/ldap/servers/plugins/replication/repl5_replica.c
+++ b/ldap/servers/plugins/replication/repl5_replica.c
@@ -665,10 +665,11 @@ replica_set_ruv (Replica *r, RUV *ruv)
* inbound replication session operation, and needs to update its
* local RUV.
*/
-void
+int
replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl)
{
char csn_str[CSN_STRSIZE];
+ int rc = RUV_SUCCESS;
PR_ASSERT(NULL != r);
PR_ASSERT(NULL != updated_csn);
@@ -681,11 +682,13 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl)
{
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_update_ruv: replica "
"is NULL\n");
+ rc = RUV_BAD_DATA;
}
else if (NULL == updated_csn)
{
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_update_ruv: csn "
"is NULL when updating replica %s\n", slapi_sdn_get_dn(r->repl_root));
+ rc = RUV_BAD_DATA;
}
else
{
@@ -718,8 +721,17 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl)
}
}
/* Update max csn for local and remote replicas */
- if (ruv_update_ruv (ruv, updated_csn, replica_purl, rid == r->repl_rid)
- != RUV_SUCCESS)
+ rc = ruv_update_ruv (ruv, updated_csn, replica_purl, rid == r->repl_rid);
+ if (RUV_COVERS_CSN == rc)
+ {
+ slapi_log_error(SLAPI_LOG_REPL,
+ repl_plugin_name, "replica_update_ruv: RUV "
+ "for replica %s already covers max_csn = %s\n",
+ slapi_sdn_get_dn(r->repl_root),
+ csn_as_string(updated_csn, PR_FALSE, csn_str));
+ /* RUV is not dirty - no write needed */
+ }
+ else if (RUV_SUCCESS != rc)
{
slapi_log_error(SLAPI_LOG_FATAL,
repl_plugin_name, "replica_update_ruv: unable "
@@ -727,14 +739,18 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl)
slapi_sdn_get_dn(r->repl_root),
csn_as_string(updated_csn, PR_FALSE, csn_str));
}
-
- r->repl_ruv_dirty = PR_TRUE;
+ else
+ {
+ /* RUV updated - mark as dirty */
+ r->repl_ruv_dirty = PR_TRUE;
+ }
}
else
{
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
"replica_update_ruv: unable to get RUV object for replica "
"%s\n", slapi_sdn_get_dn(r->repl_root));
+ rc = RUV_NOTFOUND;
}
}
else
@@ -742,9 +758,11 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl)
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_update_ruv: "
"unable to initialize RUV for replica %s\n",
slapi_sdn_get_dn(r->repl_root));
+ rc = RUV_NOTFOUND;
}
PR_Unlock(r->repl_lock);
}
+ return rc;
}
/*
@@ -2432,7 +2450,11 @@ replica_update_state (time_t when, void *arg)
{
/* EY: the consumer needs to flush ruv to disk. */
PR_Unlock(r->repl_lock);
- replica_write_ruv(r);
+ if (replica_write_ruv(r)) {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "_replica_update_state: failed write RUV for %s\n",
+ slapi_sdn_get_dn (r->repl_root));
+ }
goto done;
}
@@ -2503,7 +2525,11 @@ replica_update_state (time_t when, void *arg)
}
/* update RUV - performs its own locking */
- replica_write_ruv (r);
+ if (replica_write_ruv(r)) {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "_replica_update_state: failed write RUV for %s\n",
+ slapi_sdn_get_dn (r->repl_root));
+ }
/* since this is the only place this value is changed and we are
guaranteed that only one thread enters the function, its ok
@@ -2519,10 +2545,10 @@ done:
object_release (replica_object);
}
-void
+int
replica_write_ruv (Replica *r)
{
- int rc;
+ int rc = LDAP_SUCCESS;
Slapi_Mod smod;
Slapi_Mod smod_last_modified;
LDAPMod *mods [3];
@@ -2535,7 +2561,7 @@ replica_write_ruv (Replica *r)
if (!r->repl_ruv_dirty)
{
PR_Unlock(r->repl_lock);
- return;
+ return rc;
}
PR_ASSERT (r->repl_ruv);
@@ -2592,6 +2618,8 @@ replica_write_ruv (Replica *r)
slapi_mod_done (&smod);
slapi_mod_done (&smod_last_modified);
slapi_pblock_destroy (pb);
+
+ return rc;
}
@@ -2612,6 +2640,7 @@ replica_ruv_smods_for_op( Slapi_PBlock *pb, char **uniqueid, Slapi_Mods **smods
Slapi_Mod smod_last_modified;
Slapi_Operation *op;
Slapi_Entry *target_entry = NULL;
+ int rc = 0;
slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &target_entry);
if (target_entry && is_ruv_tombstone_entry(target_entry)) {
@@ -2650,19 +2679,32 @@ replica_ruv_smods_for_op( Slapi_PBlock *pb, char **uniqueid, Slapi_Mods **smods
object_release (ruv_obj);
object_release (replica_obj);
- ruv_set_max_csn( ruv_copy, opcsn, NULL );
-
- ruv_to_smod( ruv_copy, &smod );
- ruv_last_modified_to_smod( ruv_copy, &smod_last_modified );
+ rc = ruv_set_max_csn_ext( ruv_copy, opcsn, NULL, PR_TRUE );
+ if (rc == RUV_COVERS_CSN) { /* change would "revert" RUV - ignored */
+ rc = 0; /* tell caller to ignore */
+ } else if (rc == RUV_SUCCESS) {
+ rc = 1; /* tell caller success */
+ } else { /* error */
+ rc = -1; /* tell caller error */
+ }
+ if (rc == 1) {
+ ruv_to_smod( ruv_copy, &smod );
+ ruv_last_modified_to_smod( ruv_copy, &smod_last_modified );
+ }
ruv_destroy( &ruv_copy );
- *smods = slapi_mods_new();
- slapi_mods_add_smod(*smods, &smod);
- slapi_mods_add_smod(*smods, &smod_last_modified);
- *uniqueid = slapi_ch_strdup( RUV_STORAGE_ENTRY_UNIQUEID );
+ if (rc == 1) {
+ *smods = slapi_mods_new();
+ slapi_mods_add_smod(*smods, &smod);
+ slapi_mods_add_smod(*smods, &smod_last_modified);
+ *uniqueid = slapi_ch_strdup( RUV_STORAGE_ENTRY_UNIQUEID );
+ } else {
+ *smods = NULL;
+ *uniqueid = NULL;
+ }
- return (1);
+ return rc;
}
@@ -3407,7 +3449,9 @@ replica_strip_cleaned_rids(Replica *r)
while(rid[i] != 0){
ruv_delete_replica(ruv, rid[i]);
replica_set_ruv_dirty(r);
- replica_write_ruv(r);
+ if (replica_write_ruv(r)) {
+ slapi_log_error (SLAPI_LOG_REPL, "replica_strip_cleaned_rids", "failed to write RUV\n");
+ }
i++;
}
object_release(RUVObj);
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index e28e345..79ac5b0 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -1229,7 +1229,9 @@ replica_execute_cleanruv_task (Object *r, ReplicaId rid, char *returntext /* not
}
rc = ruv_delete_replica(local_ruv, rid);
replica_set_ruv_dirty(replica);
- replica_write_ruv(replica);
+ if (replica_write_ruv(replica)) {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanruv_task: could not write RUV\n");
+ }
object_release(RUVObj);
/* Update Mapping Tree to reflect RUV changes */
diff --git a/ldap/servers/plugins/replication/repl5_ruv.c b/ldap/servers/plugins/replication/repl5_ruv.c
index 107c4f0..7395195 100644
--- a/ldap/servers/plugins/replication/repl5_ruv.c
+++ b/ldap/servers/plugins/replication/repl5_ruv.c
@@ -677,26 +677,34 @@ set_min_csn_nolock(RUV *ruv, const CSN *min_csn, const char *replica_purl)
}
static int
-set_max_csn_nolock(RUV *ruv, const CSN *max_csn, const char *replica_purl)
+set_max_csn_nolock_ext(RUV *ruv, const CSN *max_csn, const char *replica_purl, PRBool must_be_greater)
{
- int return_value;
+ int return_value = RUV_SUCCESS;
ReplicaId rid = csn_get_replicaid (max_csn);
RUVElement *replica = ruvGetReplica (ruv, rid);
- if (NULL == replica)
- {
- replica = ruvAddReplica (ruv, max_csn, replica_purl);
- if (replica)
- return_value = RUV_SUCCESS;
- else
- return_value = RUV_MEMORY_ERROR;
- }
- else
- {
- if (replica_purl && replica->replica_purl == NULL)
- replica->replica_purl = slapi_ch_strdup (replica_purl);
- csn_free(&replica->csn);
- replica->csn = csn_dup(max_csn);
- replica->last_modified = current_time();
+ if (NULL == replica) {
+ replica = ruvAddReplica (ruv, max_csn, replica_purl);
+ if (replica)
+ return_value = RUV_SUCCESS;
+ else
+ return_value = RUV_MEMORY_ERROR;
+ } else {
+ if (replica_purl && replica->replica_purl == NULL)
+ replica->replica_purl = slapi_ch_strdup (replica_purl);
+ if (!must_be_greater || (csn_compare(replica->csn, max_csn) < 0)) {
+ csn_free(&replica->csn);
+ replica->csn = csn_dup(max_csn);
+ replica->last_modified = current_time();
+ } else {
+ char csn1[CSN_STRSIZE+1];
+ char csn2[CSN_STRSIZE+1];
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "set_max_csn_nolock_ext: new CSN [%s] for replica ID [%d] "
+ "is less than the existing max CSN [%s] - ignoring\n",
+ csn_as_string(max_csn, PR_FALSE, csn1), rid,
+ csn_as_string(replica->csn, PR_FALSE, csn2));
+ return_value = RUV_COVERS_CSN;
+ }
return_value = RUV_SUCCESS;
}
return return_value;
@@ -716,9 +724,15 @@ ruv_set_min_csn(RUV *ruv, const CSN *min_csn, const char *replica_purl)
int
ruv_set_max_csn(RUV *ruv, const CSN *max_csn, const char *replica_purl)
{
+ return ruv_set_max_csn_ext(ruv, max_csn, replica_purl, PR_FALSE);
+}
+
+int
+ruv_set_max_csn_ext(RUV *ruv, const CSN *max_csn, const char *replica_purl, PRBool must_be_greater)
+{
int return_value;
slapi_rwlock_wrlock (ruv->lock);
- return_value = set_max_csn_nolock(ruv, max_csn, replica_purl);
+ return_value = set_max_csn_nolock_ext(ruv, max_csn, replica_purl, must_be_greater);
slapi_rwlock_unlock (ruv->lock);
return return_value;
}
@@ -1666,8 +1680,9 @@ int ruv_update_ruv (RUV *ruv, const CSN *csn, const char *replica_purl, PRBool i
* generated by this replica, we need to set the first_csn as the min csn in the
* ruv */
set_min_csn_nolock(ruv, first_csn, replica_purl);
- }
- set_max_csn_nolock(ruv, max_csn, replica_purl);
+ }
+ /* only update the max_csn in the RUV if it is greater than the existing one */
+ rc = set_max_csn_nolock_ext(ruv, max_csn, replica_purl, PR_TRUE /* must be greater */);
/* It is possible that first_csn points to max_csn.
We need to free it once */
if (max_csn != first_csn) {
diff --git a/ldap/servers/plugins/replication/repl5_ruv.h b/ldap/servers/plugins/replication/repl5_ruv.h
index 036951f..799dc7f 100644
--- a/ldap/servers/plugins/replication/repl5_ruv.h
+++ b/ldap/servers/plugins/replication/repl5_ruv.h
@@ -113,6 +113,7 @@ int ruv_get_smallest_csn_for_replica(const RUV *ruv, ReplicaId rid, CSN **csn);
int ruv_set_csns(RUV *ruv, const CSN *csn, const char *replica_purl);
int ruv_set_csns_keep_smallest(RUV *ruv, const CSN *csn);
int ruv_set_max_csn(RUV *ruv, const CSN *max_csn, const char *replica_purl);
+int ruv_set_max_csn_ext(RUV *ruv, const CSN *max_csn, const char *replica_purl, PRBool must_be_greater);
int ruv_set_min_csn(RUV *ruv, const CSN *min_csn, const char *replica_purl);
const char *ruv_get_purl_for_replica(const RUV *ruv, ReplicaId rid);
char *ruv_get_replica_generation (const RUV *ruv);
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c
index eab2ae1..708ccfa 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c
@@ -344,6 +344,11 @@ ldbm_back_add( Slapi_PBlock *pb )
goto error_return;
}
}
+ if (ruv_c_init) {
+ /* reset the ruv txn stuff */
+ modify_term(&ruv_c, be);
+ ruv_c_init = 0;
+ }
/* We're re-trying */
LDAPDebug0Args(LDAP_DEBUG_BACKLDBM, "Add Retrying Transaction\n");
@@ -759,19 +764,6 @@ ldbm_back_add( Slapi_PBlock *pb )
parententry = NULL;
}
- if (!is_ruv && !is_fixup_operation) {
- ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
- if (-1 == ruv_c_init) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm_back_add: ldbm_txn_ruv_modify_context "
- "failed to construct RUV modify context\n",
- 0, 0, 0);
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- retval = 0;
- goto error_return;
- }
- }
-
if ( (originalentry = backentry_dup(addingentry )) == NULL ) {
ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
@@ -952,6 +944,19 @@ ldbm_back_add( Slapi_PBlock *pb )
}
}
+ if (!is_ruv && !is_fixup_operation) {
+ ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
+ if (-1 == ruv_c_init) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ldbm_back_add: ldbm_txn_ruv_modify_context "
+ "failed to construct RUV modify context\n",
+ 0, 0, 0);
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ retval = 0;
+ goto error_return;
+ }
+ }
+
if (ruv_c_init) {
retval = modify_update_all( be, pb, &ruv_c, &txn );
if (DB_LOCK_DEADLOCK == retval) {
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
index 6efa03e..be73e04 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
@@ -235,6 +235,12 @@ ldbm_back_delete( Slapi_PBlock *pb )
e_in_cache = 1;
}
+ if (ruv_c_init) {
+ /* reset the ruv txn stuff */
+ modify_term(&ruv_c, be);
+ ruv_c_init = 0;
+ }
+
/* We're re-trying */
LDAPDebug0Args(LDAP_DEBUG_BACKLDBM,
"Delete Retrying Transaction\n");
@@ -550,19 +556,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
goto error_return;
}
}
-
- if (!is_ruv && !is_fixup_operation && !delete_tombstone_entry) {
- ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
- if (-1 == ruv_c_init) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm_back_delete: ldbm_txn_ruv_modify_context "
- "failed to construct RUV modify context\n",
- 0, 0, 0);
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- retval = 0;
- goto error_return;
- }
- }
} /* if (0 == retry_count) just once */
else {
/* call the transaction pre delete plugins not just once
@@ -1028,6 +1021,19 @@ ldbm_back_delete( Slapi_PBlock *pb )
}
}
+ if (!is_ruv && !is_fixup_operation && !delete_tombstone_entry) {
+ ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
+ if (-1 == ruv_c_init) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ldbm_back_delete: ldbm_txn_ruv_modify_context "
+ "failed to construct RUV modify context\n",
+ 0, 0, 0);
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ retval = 0;
+ goto error_return;
+ }
+ }
+
if (ruv_c_init) {
retval = modify_update_all( be, pb, &ruv_c, &txn );
if (DB_LOCK_DEADLOCK == retval) {
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
index b6a2298..b5bdb41 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
@@ -437,6 +437,12 @@ ldbm_back_modify( Slapi_PBlock *pb )
goto error_return;
}
+ if (ruv_c_init) {
+ /* reset the ruv txn stuff */
+ modify_term(&ruv_c, be);
+ ruv_c_init = 0;
+ }
+
LDAPDebug0Args(LDAP_DEBUG_BACKLDBM,
"Modify Retrying Transaction\n");
#ifndef LDBM_NO_BACKOFF_DELAY
@@ -550,19 +556,6 @@ ldbm_back_modify( Slapi_PBlock *pb )
goto error_return;
}
- if (!is_ruv && !is_fixup_operation) {
- ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
- if (-1 == ruv_c_init) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm_back_modify: ldbm_txn_ruv_modify_context "
- "failed to construct RUV modify context\n",
- 0, 0, 0);
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- retval = 0;
- goto error_return;
- }
- }
-
/*
* Grab a copy of the mods and the entry in case the be_txn_preop changes
* the them. If we have a failure, then we need to reset the mods to their
@@ -669,6 +662,19 @@ ldbm_back_modify( Slapi_PBlock *pb )
}
+ if (!is_ruv && !is_fixup_operation) {
+ ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
+ if (-1 == ruv_c_init) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ldbm_back_modify: ldbm_txn_ruv_modify_context "
+ "failed to construct RUV modify context\n",
+ 0, 0, 0);
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ retval = 0;
+ goto error_return;
+ }
+ }
+
if (ruv_c_init) {
retval = modify_update_all( be, pb, &ruv_c, &txn );
if (DB_LOCK_DEADLOCK == retval) {
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
index 8f898aa..8944b6c 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
@@ -309,6 +309,11 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
goto error_return;
}
+ if (ruv_c_init) {
+ /* reset the ruv txn stuff */
+ modify_term(&ruv_c, be);
+ ruv_c_init = 0;
+ }
/* We're re-trying */
LDAPDebug0Args(LDAP_DEBUG_BACKLDBM,
"Modrdn Retrying Transaction\n");
@@ -846,19 +851,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
/* JCM - A subtree move could break ACIs, static groups, and dynamic groups. */
}
- if (!is_ruv && !is_fixup_operation) {
- ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
- if (-1 == ruv_c_init) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm_back_modrdn: ldbm_txn_ruv_modify_context "
- "failed to construct RUV modify context\n",
- 0, 0, 0);
- ldap_result_code = LDAP_OPERATIONS_ERROR;
- retval = 0;
- goto error_return;
- }
- }
-
/*
* make copies of the originals, no need to copy the mods because
* we have already copied them
@@ -1065,6 +1057,19 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
goto error_return;
}
+ if (!is_ruv && !is_fixup_operation) {
+ ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
+ if (-1 == ruv_c_init) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ldbm_back_modrdn: ldbm_txn_ruv_modify_context "
+ "failed to construct RUV modify context\n",
+ 0, 0, 0);
+ ldap_result_code = LDAP_OPERATIONS_ERROR;
+ retval = 0;
+ goto error_return;
+ }
+ }
+
if (ruv_c_init) {
retval = modify_update_all( be, pb, &ruv_c, &txn );
if (DB_LOCK_DEADLOCK == retval) {
diff --git a/ldap/servers/slapd/back-ldbm/misc.c b/ldap/servers/slapd/back-ldbm/misc.c
index 87262c5..00d48b3 100644
--- a/ldap/servers/slapd/back-ldbm/misc.c
+++ b/ldap/servers/slapd/back-ldbm/misc.c
@@ -426,6 +426,7 @@ ldbm_txn_ruv_modify_context( Slapi_PBlock *pb, modify_context *mc )
/* Either something went wrong when the RUV callback tried to assemble
* the updates for us, or there were no updates because the op doesn't
* target a replica. */
+ /* or, the CSN is already covered by the RUV */
if (1 != rc || NULL == smods || NULL == uniqueid) {
return (rc);
}
10 years, 10 months
Branch '389-ds-base-1.3.0' - ldap/servers
by Richard Allen Megginson
ldap/servers/plugins/replication/repl5.h | 4
ldap/servers/plugins/replication/repl5_plugins.c | 29 ++++-
ldap/servers/plugins/replication/repl5_replica.c | 84 ++++++++++++----
ldap/servers/plugins/replication/repl5_replica_config.c | 4
ldap/servers/plugins/replication/repl5_ruv.c | 55 ++++++----
ldap/servers/plugins/replication/repl5_ruv.h | 1
ldap/servers/slapd/back-ldbm/ldbm_add.c | 31 +++--
ldap/servers/slapd/back-ldbm/ldbm_delete.c | 32 +++---
ldap/servers/slapd/back-ldbm/ldbm_modify.c | 32 +++---
ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 31 +++--
ldap/servers/slapd/back-ldbm/misc.c | 1
11 files changed, 205 insertions(+), 99 deletions(-)
New commits:
commit 3108793c15697f6977bbfd85d5857aaa9e0aa4d9
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Tue Jul 9 11:38:39 2013 -0600
Ticket #47392 - ldbm errors when adding/modifying/deleting entries
https://fedorahosted.org/389/ticket/47392
Reviewed by: lkrispenz (Thanks!)
Branch: 389-ds-base-1.3.1
Fix Description: The problem is caused by cache consistency issues with the
RUV entry. Before the txn starts, we grab a pointer to the RUV entry in
the cache. When DNA (or any betxnpreop plugin) updates the database, it
will also grab a pointer to the cached RUV entry and modify it, out from
under the parent txn. This can also cause the max CSN in the RUV to go
backwards - the nested txn will have a later CSN which will be
overwritten by the earlier CSN from the parent txn.
The fix is to move the ldbm_ruv_txn code inside the transaction loop after
the betxnpreop plugins have been run. Also have to add modify_term inside
the retry logic to cancel the modify ruv txn stuff in order to retry.
The other part of the fix is to tell the code that updates the max CSN
in the RUV to skip changes that would cause the RUV to go backwards,
and return a code to the caller that tells the caller that the CSN is
already covered. The code that updates the RUV for the txn will skip
the modify operations in that case.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
(cherry picked from commit ff7fb870fb0034857b855d2c9e769cdf00237aad)
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index f1d6ef4..b15f268 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -549,7 +549,7 @@ void replica_replace_flags (Replica *r, PRUint32 flags);
void replica_dump(Replica *r);
void replica_set_enabled (Replica *r, PRBool enable);
Object *replica_get_replica_from_dn (const Slapi_DN *dn);
-void replica_update_ruv(Replica *replica, const CSN *csn, const char *replica_purl);
+int replica_update_ruv(Replica *replica, const CSN *csn, const char *replica_purl);
Object *replica_get_replica_for_op (Slapi_PBlock *pb);
/* the functions below manipulate replica hash */
int replica_init_name_hash ();
@@ -581,7 +581,7 @@ void replica_set_purge_delay (Replica *r, PRUint32 purge_delay);
void replica_set_tombstone_reap_interval (Replica *r, long interval);
void replica_update_ruv_consumer (Replica *r, RUV *supplier_ruv);
void replica_set_ruv_dirty (Replica *r);
-void replica_write_ruv (Replica *r);
+int replica_write_ruv (Replica *r);
char *replica_get_dn(Replica *r);
void replica_check_for_tasks(Replica*r, Slapi_Entry *e);
diff --git a/ldap/servers/plugins/replication/repl5_plugins.c b/ldap/servers/plugins/replication/repl5_plugins.c
index 43c1596..01ac03c 100644
--- a/ldap/servers/plugins/replication/repl5_plugins.c
+++ b/ldap/servers/plugins/replication/repl5_plugins.c
@@ -1081,14 +1081,15 @@ copy_operation_parameters(Slapi_PBlock *pb)
* locally-processed update. This is called for both replicated
* and non-replicated operations.
*/
-static void
+static int
update_ruv_component(Replica *replica, CSN *opcsn, Slapi_PBlock *pb)
{
PRBool legacy;
char *purl;
+ int rc = RUV_NOTFOUND;
if (!replica || !opcsn)
- return;
+ return rc;
/* Replica configured, so update its ruv */
legacy = replica_is_legacy_consumer (replica);
@@ -1097,12 +1098,13 @@ update_ruv_component(Replica *replica, CSN *opcsn, Slapi_PBlock *pb)
else
purl = (char*)replica_get_purl_for_op (replica, pb, opcsn);
- replica_update_ruv(replica, opcsn, purl);
+ rc = replica_update_ruv(replica, opcsn, purl);
if (legacy)
{
slapi_ch_free ((void**)&purl);
}
+ return rc;
}
/*
@@ -1264,11 +1266,30 @@ write_changelog_and_ruv (Slapi_PBlock *pb)
just read from the changelog in either the supplier or consumer ruv
*/
if (0 == return_value) {
+ char csn_str[CSN_STRSIZE];
CSN *opcsn;
+ int rc;
slapi_pblock_get( pb, SLAPI_OPERATION, &op );
opcsn = operation_get_csn(op);
- update_ruv_component(r, opcsn, pb);
+ rc = update_ruv_component(r, opcsn, pb);
+ if (RUV_COVERS_CSN == rc) {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "write_changelog_and_ruv: RUV already covers csn for "
+ "%s (uniqid: %s, optype: %lu) csn %s\n",
+ REPL_GET_DN(&op_params->target_address),
+ op_params->target_address.uniqueid,
+ op_params->operation_type,
+ csn_as_string(op_params->csn, PR_FALSE, csn_str));
+ } else if (rc != RUV_SUCCESS) {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+ "write_changelog_and_ruv: failed to update RUV for "
+ "%s (uniqid: %s, optype: %lu) to changelog csn %s\n",
+ REPL_GET_DN(&op_params->target_address),
+ op_params->target_address.uniqueid,
+ op_params->operation_type,
+ csn_as_string(op_params->csn, PR_FALSE, csn_str));
+ }
}
object_release (repl_obj);
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
index 3d7677b..81c09d7 100644
--- a/ldap/servers/plugins/replication/repl5_replica.c
+++ b/ldap/servers/plugins/replication/repl5_replica.c
@@ -657,10 +657,11 @@ replica_set_ruv (Replica *r, RUV *ruv)
* inbound replication session operation, and needs to update its
* local RUV.
*/
-void
+int
replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl)
{
char csn_str[CSN_STRSIZE];
+ int rc = RUV_SUCCESS;
PR_ASSERT(NULL != r);
PR_ASSERT(NULL != updated_csn);
@@ -673,11 +674,13 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl)
{
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_update_ruv: replica "
"is NULL\n");
+ rc = RUV_BAD_DATA;
}
else if (NULL == updated_csn)
{
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_update_ruv: csn "
"is NULL when updating replica %s\n", slapi_sdn_get_dn(r->repl_root));
+ rc = RUV_BAD_DATA;
}
else
{
@@ -710,8 +713,17 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl)
}
}
/* Update max csn for local and remote replicas */
- if (ruv_update_ruv (ruv, updated_csn, replica_purl, rid == r->repl_rid)
- != RUV_SUCCESS)
+ rc = ruv_update_ruv (ruv, updated_csn, replica_purl, rid == r->repl_rid);
+ if (RUV_COVERS_CSN == rc)
+ {
+ slapi_log_error(SLAPI_LOG_REPL,
+ repl_plugin_name, "replica_update_ruv: RUV "
+ "for replica %s already covers max_csn = %s\n",
+ slapi_sdn_get_dn(r->repl_root),
+ csn_as_string(updated_csn, PR_FALSE, csn_str));
+ /* RUV is not dirty - no write needed */
+ }
+ else if (RUV_SUCCESS != rc)
{
slapi_log_error(SLAPI_LOG_FATAL,
repl_plugin_name, "replica_update_ruv: unable "
@@ -719,14 +731,18 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl)
slapi_sdn_get_dn(r->repl_root),
csn_as_string(updated_csn, PR_FALSE, csn_str));
}
-
- r->repl_ruv_dirty = PR_TRUE;
+ else
+ {
+ /* RUV updated - mark as dirty */
+ r->repl_ruv_dirty = PR_TRUE;
+ }
}
else
{
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
"replica_update_ruv: unable to get RUV object for replica "
"%s\n", slapi_sdn_get_dn(r->repl_root));
+ rc = RUV_NOTFOUND;
}
}
else
@@ -734,9 +750,11 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl)
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_update_ruv: "
"unable to initialize RUV for replica %s\n",
slapi_sdn_get_dn(r->repl_root));
+ rc = RUV_NOTFOUND;
}
PR_Unlock(r->repl_lock);
}
+ return rc;
}
/*
@@ -2400,7 +2418,11 @@ _replica_update_state (time_t when, void *arg)
{
/* EY: the consumer needs to flush ruv to disk. */
PR_Unlock(r->repl_lock);
- replica_write_ruv(r);
+ if (replica_write_ruv(r)) {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "_replica_update_state: failed write RUV for %s\n",
+ slapi_sdn_get_dn (r->repl_root));
+ }
goto done;
}
@@ -2471,7 +2493,11 @@ _replica_update_state (time_t when, void *arg)
}
/* update RUV - performs its own locking */
- replica_write_ruv (r);
+ if (replica_write_ruv(r)) {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "_replica_update_state: failed write RUV for %s\n",
+ slapi_sdn_get_dn (r->repl_root));
+ }
/* since this is the only place this value is changed and we are
guaranteed that only one thread enters the function, its ok
@@ -2487,10 +2513,10 @@ done:
object_release (replica_object);
}
-void
+int
replica_write_ruv (Replica *r)
{
- int rc;
+ int rc = LDAP_SUCCESS;
Slapi_Mod smod;
Slapi_Mod smod_last_modified;
LDAPMod *mods [3];
@@ -2503,7 +2529,7 @@ replica_write_ruv (Replica *r)
if (!r->repl_ruv_dirty)
{
PR_Unlock(r->repl_lock);
- return;
+ return rc;
}
PR_ASSERT (r->repl_ruv);
@@ -2560,6 +2586,8 @@ replica_write_ruv (Replica *r)
slapi_mod_done (&smod);
slapi_mod_done (&smod_last_modified);
slapi_pblock_destroy (pb);
+
+ return rc;
}
@@ -2580,6 +2608,7 @@ replica_ruv_smods_for_op( Slapi_PBlock *pb, char **uniqueid, Slapi_Mods **smods
Slapi_Mod smod_last_modified;
Slapi_Operation *op;
Slapi_Entry *target_entry = NULL;
+ int rc = 0;
slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &target_entry);
if (target_entry && is_ruv_tombstone_entry(target_entry)) {
@@ -2618,19 +2647,32 @@ replica_ruv_smods_for_op( Slapi_PBlock *pb, char **uniqueid, Slapi_Mods **smods
object_release (ruv_obj);
object_release (replica_obj);
- ruv_set_max_csn( ruv_copy, opcsn, NULL );
-
- ruv_to_smod( ruv_copy, &smod );
- ruv_last_modified_to_smod( ruv_copy, &smod_last_modified );
+ rc = ruv_set_max_csn_ext( ruv_copy, opcsn, NULL, PR_TRUE );
+ if (rc == RUV_COVERS_CSN) { /* change would "revert" RUV - ignored */
+ rc = 0; /* tell caller to ignore */
+ } else if (rc == RUV_SUCCESS) {
+ rc = 1; /* tell caller success */
+ } else { /* error */
+ rc = -1; /* tell caller error */
+ }
+ if (rc == 1) {
+ ruv_to_smod( ruv_copy, &smod );
+ ruv_last_modified_to_smod( ruv_copy, &smod_last_modified );
+ }
ruv_destroy( &ruv_copy );
- *smods = slapi_mods_new();
- slapi_mods_add_smod(*smods, &smod);
- slapi_mods_add_smod(*smods, &smod_last_modified);
- *uniqueid = slapi_ch_strdup( RUV_STORAGE_ENTRY_UNIQUEID );
+ if (rc == 1) {
+ *smods = slapi_mods_new();
+ slapi_mods_add_smod(*smods, &smod);
+ slapi_mods_add_smod(*smods, &smod_last_modified);
+ *uniqueid = slapi_ch_strdup( RUV_STORAGE_ENTRY_UNIQUEID );
+ } else {
+ *smods = NULL;
+ *uniqueid = NULL;
+ }
- return (1);
+ return rc;
}
@@ -3375,7 +3417,9 @@ replica_strip_cleaned_rids(Replica *r)
while(rid[i] != 0){
ruv_delete_replica(ruv, rid[i]);
replica_set_ruv_dirty(r);
- replica_write_ruv(r);
+ if (replica_write_ruv(r)) {
+ slapi_log_error (SLAPI_LOG_REPL, "replica_strip_cleaned_rids", "failed to write RUV\n");
+ }
i++;
}
object_release(RUVObj);
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index c770bcb..3e14fc2 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -1200,7 +1200,9 @@ replica_execute_cleanruv_task (Object *r, ReplicaId rid, char *returntext /* not
}
rc = ruv_delete_replica(local_ruv, rid);
replica_set_ruv_dirty(replica);
- replica_write_ruv(replica);
+ if (replica_write_ruv(replica)) {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanruv_task: could not write RUV\n");
+ }
object_release(RUVObj);
/* Update Mapping Tree to reflect RUV changes */
diff --git a/ldap/servers/plugins/replication/repl5_ruv.c b/ldap/servers/plugins/replication/repl5_ruv.c
index 8fbd89c..2808c58 100644
--- a/ldap/servers/plugins/replication/repl5_ruv.c
+++ b/ldap/servers/plugins/replication/repl5_ruv.c
@@ -665,26 +665,34 @@ set_min_csn_nolock(RUV *ruv, const CSN *min_csn, const char *replica_purl)
}
static int
-set_max_csn_nolock(RUV *ruv, const CSN *max_csn, const char *replica_purl)
+set_max_csn_nolock_ext(RUV *ruv, const CSN *max_csn, const char *replica_purl, PRBool must_be_greater)
{
- int return_value;
+ int return_value = RUV_SUCCESS;
ReplicaId rid = csn_get_replicaid (max_csn);
RUVElement *replica = ruvGetReplica (ruv, rid);
- if (NULL == replica)
- {
- replica = ruvAddReplica (ruv, max_csn, replica_purl);
- if (replica)
- return_value = RUV_SUCCESS;
- else
- return_value = RUV_MEMORY_ERROR;
- }
- else
- {
- if (replica_purl && replica->replica_purl == NULL)
- replica->replica_purl = slapi_ch_strdup (replica_purl);
- csn_free(&replica->csn);
- replica->csn = csn_dup(max_csn);
- replica->last_modified = current_time();
+ if (NULL == replica) {
+ replica = ruvAddReplica (ruv, max_csn, replica_purl);
+ if (replica)
+ return_value = RUV_SUCCESS;
+ else
+ return_value = RUV_MEMORY_ERROR;
+ } else {
+ if (replica_purl && replica->replica_purl == NULL)
+ replica->replica_purl = slapi_ch_strdup (replica_purl);
+ if (!must_be_greater || (csn_compare(replica->csn, max_csn) < 0)) {
+ csn_free(&replica->csn);
+ replica->csn = csn_dup(max_csn);
+ replica->last_modified = current_time();
+ } else {
+ char csn1[CSN_STRSIZE+1];
+ char csn2[CSN_STRSIZE+1];
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "set_max_csn_nolock_ext: new CSN [%s] for replica ID [%d] "
+ "is less than the existing max CSN [%s] - ignoring\n",
+ csn_as_string(max_csn, PR_FALSE, csn1), rid,
+ csn_as_string(replica->csn, PR_FALSE, csn2));
+ return_value = RUV_COVERS_CSN;
+ }
return_value = RUV_SUCCESS;
}
return return_value;
@@ -704,9 +712,15 @@ ruv_set_min_csn(RUV *ruv, const CSN *min_csn, const char *replica_purl)
int
ruv_set_max_csn(RUV *ruv, const CSN *max_csn, const char *replica_purl)
{
+ return ruv_set_max_csn_ext(ruv, max_csn, replica_purl, PR_FALSE);
+}
+
+int
+ruv_set_max_csn_ext(RUV *ruv, const CSN *max_csn, const char *replica_purl, PRBool must_be_greater)
+{
int return_value;
slapi_rwlock_wrlock (ruv->lock);
- return_value = set_max_csn_nolock(ruv, max_csn, replica_purl);
+ return_value = set_max_csn_nolock_ext(ruv, max_csn, replica_purl, must_be_greater);
slapi_rwlock_unlock (ruv->lock);
return return_value;
}
@@ -1654,8 +1668,9 @@ int ruv_update_ruv (RUV *ruv, const CSN *csn, const char *replica_purl, PRBool i
* generated by this replica, we need to set the first_csn as the min csn in the
* ruv */
set_min_csn_nolock(ruv, first_csn, replica_purl);
- }
- set_max_csn_nolock(ruv, max_csn, replica_purl);
+ }
+ /* only update the max_csn in the RUV if it is greater than the existing one */
+ rc = set_max_csn_nolock_ext(ruv, max_csn, replica_purl, PR_TRUE /* must be greater */);
/* It is possible that first_csn points to max_csn.
We need to free it once */
if (max_csn != first_csn) {
diff --git a/ldap/servers/plugins/replication/repl5_ruv.h b/ldap/servers/plugins/replication/repl5_ruv.h
index 944f5ed..fdc8af2 100644
--- a/ldap/servers/plugins/replication/repl5_ruv.h
+++ b/ldap/servers/plugins/replication/repl5_ruv.h
@@ -108,6 +108,7 @@ int ruv_get_smallest_csn_for_replica(const RUV *ruv, ReplicaId rid, CSN **csn);
int ruv_set_csns(RUV *ruv, const CSN *csn, const char *replica_purl);
int ruv_set_csns_keep_smallest(RUV *ruv, const CSN *csn);
int ruv_set_max_csn(RUV *ruv, const CSN *max_csn, const char *replica_purl);
+int ruv_set_max_csn_ext(RUV *ruv, const CSN *max_csn, const char *replica_purl, PRBool must_be_greater);
int ruv_set_min_csn(RUV *ruv, const CSN *min_csn, const char *replica_purl);
const char *ruv_get_purl_for_replica(const RUV *ruv, ReplicaId rid);
char *ruv_get_replica_generation (const RUV *ruv);
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c
index eab2ae1..708ccfa 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c
@@ -344,6 +344,11 @@ ldbm_back_add( Slapi_PBlock *pb )
goto error_return;
}
}
+ if (ruv_c_init) {
+ /* reset the ruv txn stuff */
+ modify_term(&ruv_c, be);
+ ruv_c_init = 0;
+ }
/* We're re-trying */
LDAPDebug0Args(LDAP_DEBUG_BACKLDBM, "Add Retrying Transaction\n");
@@ -759,19 +764,6 @@ ldbm_back_add( Slapi_PBlock *pb )
parententry = NULL;
}
- if (!is_ruv && !is_fixup_operation) {
- ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
- if (-1 == ruv_c_init) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm_back_add: ldbm_txn_ruv_modify_context "
- "failed to construct RUV modify context\n",
- 0, 0, 0);
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- retval = 0;
- goto error_return;
- }
- }
-
if ( (originalentry = backentry_dup(addingentry )) == NULL ) {
ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
@@ -952,6 +944,19 @@ ldbm_back_add( Slapi_PBlock *pb )
}
}
+ if (!is_ruv && !is_fixup_operation) {
+ ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
+ if (-1 == ruv_c_init) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ldbm_back_add: ldbm_txn_ruv_modify_context "
+ "failed to construct RUV modify context\n",
+ 0, 0, 0);
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ retval = 0;
+ goto error_return;
+ }
+ }
+
if (ruv_c_init) {
retval = modify_update_all( be, pb, &ruv_c, &txn );
if (DB_LOCK_DEADLOCK == retval) {
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
index 6efa03e..be73e04 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
@@ -235,6 +235,12 @@ ldbm_back_delete( Slapi_PBlock *pb )
e_in_cache = 1;
}
+ if (ruv_c_init) {
+ /* reset the ruv txn stuff */
+ modify_term(&ruv_c, be);
+ ruv_c_init = 0;
+ }
+
/* We're re-trying */
LDAPDebug0Args(LDAP_DEBUG_BACKLDBM,
"Delete Retrying Transaction\n");
@@ -550,19 +556,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
goto error_return;
}
}
-
- if (!is_ruv && !is_fixup_operation && !delete_tombstone_entry) {
- ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
- if (-1 == ruv_c_init) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm_back_delete: ldbm_txn_ruv_modify_context "
- "failed to construct RUV modify context\n",
- 0, 0, 0);
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- retval = 0;
- goto error_return;
- }
- }
} /* if (0 == retry_count) just once */
else {
/* call the transaction pre delete plugins not just once
@@ -1028,6 +1021,19 @@ ldbm_back_delete( Slapi_PBlock *pb )
}
}
+ if (!is_ruv && !is_fixup_operation && !delete_tombstone_entry) {
+ ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
+ if (-1 == ruv_c_init) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ldbm_back_delete: ldbm_txn_ruv_modify_context "
+ "failed to construct RUV modify context\n",
+ 0, 0, 0);
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ retval = 0;
+ goto error_return;
+ }
+ }
+
if (ruv_c_init) {
retval = modify_update_all( be, pb, &ruv_c, &txn );
if (DB_LOCK_DEADLOCK == retval) {
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
index b6a2298..b5bdb41 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
@@ -437,6 +437,12 @@ ldbm_back_modify( Slapi_PBlock *pb )
goto error_return;
}
+ if (ruv_c_init) {
+ /* reset the ruv txn stuff */
+ modify_term(&ruv_c, be);
+ ruv_c_init = 0;
+ }
+
LDAPDebug0Args(LDAP_DEBUG_BACKLDBM,
"Modify Retrying Transaction\n");
#ifndef LDBM_NO_BACKOFF_DELAY
@@ -550,19 +556,6 @@ ldbm_back_modify( Slapi_PBlock *pb )
goto error_return;
}
- if (!is_ruv && !is_fixup_operation) {
- ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
- if (-1 == ruv_c_init) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm_back_modify: ldbm_txn_ruv_modify_context "
- "failed to construct RUV modify context\n",
- 0, 0, 0);
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- retval = 0;
- goto error_return;
- }
- }
-
/*
* Grab a copy of the mods and the entry in case the be_txn_preop changes
* the them. If we have a failure, then we need to reset the mods to their
@@ -669,6 +662,19 @@ ldbm_back_modify( Slapi_PBlock *pb )
}
+ if (!is_ruv && !is_fixup_operation) {
+ ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
+ if (-1 == ruv_c_init) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ldbm_back_modify: ldbm_txn_ruv_modify_context "
+ "failed to construct RUV modify context\n",
+ 0, 0, 0);
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ retval = 0;
+ goto error_return;
+ }
+ }
+
if (ruv_c_init) {
retval = modify_update_all( be, pb, &ruv_c, &txn );
if (DB_LOCK_DEADLOCK == retval) {
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
index 4810e03..3682485 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
@@ -309,6 +309,11 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
goto error_return;
}
+ if (ruv_c_init) {
+ /* reset the ruv txn stuff */
+ modify_term(&ruv_c, be);
+ ruv_c_init = 0;
+ }
/* We're re-trying */
LDAPDebug0Args(LDAP_DEBUG_BACKLDBM,
"Modrdn Retrying Transaction\n");
@@ -846,19 +851,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
/* JCM - A subtree move could break ACIs, static groups, and dynamic groups. */
}
- if (!is_ruv && !is_fixup_operation) {
- ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
- if (-1 == ruv_c_init) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm_back_modrdn: ldbm_txn_ruv_modify_context "
- "failed to construct RUV modify context\n",
- 0, 0, 0);
- ldap_result_code = LDAP_OPERATIONS_ERROR;
- retval = 0;
- goto error_return;
- }
- }
-
/*
* make copies of the originals, no need to copy the mods because
* we have already copied them
@@ -1065,6 +1057,19 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
goto error_return;
}
+ if (!is_ruv && !is_fixup_operation) {
+ ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
+ if (-1 == ruv_c_init) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ldbm_back_modrdn: ldbm_txn_ruv_modify_context "
+ "failed to construct RUV modify context\n",
+ 0, 0, 0);
+ ldap_result_code = LDAP_OPERATIONS_ERROR;
+ retval = 0;
+ goto error_return;
+ }
+ }
+
if (ruv_c_init) {
retval = modify_update_all( be, pb, &ruv_c, &txn );
if (DB_LOCK_DEADLOCK == retval) {
diff --git a/ldap/servers/slapd/back-ldbm/misc.c b/ldap/servers/slapd/back-ldbm/misc.c
index 56a8298..4e10458 100644
--- a/ldap/servers/slapd/back-ldbm/misc.c
+++ b/ldap/servers/slapd/back-ldbm/misc.c
@@ -426,6 +426,7 @@ ldbm_txn_ruv_modify_context( Slapi_PBlock *pb, modify_context *mc )
/* Either something went wrong when the RUV callback tried to assemble
* the updates for us, or there were no updates because the op doesn't
* target a replica. */
+ /* or, the CSN is already covered by the RUV */
if (1 != rc || NULL == smods || NULL == uniqueid) {
return (rc);
}
10 years, 10 months
Branch '389-ds-base-1.2.11' - ldap/servers
by Mark Reynolds
ldap/servers/slapd/daemon.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
New commits:
commit cd5bfad8ae5a460f1c8d14e134fcc8adbca600e7
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Wed Jul 10 11:53:15 2013 -0400
Ticket 47385 - Disk Monitoring is not triggered as expected.
Bug Description: Is using large values for the threshold the faeture does not
work.
Fix Description: There was an overflow of a integer value uses to determine
if the server should enter the "shutdown mode". Also removed
some unnecessary checks to see if disk space is continuing to drop.
https://fedorahosted.org/389/ticket/47385
Reviewed by: Noriko(Thanks!)
(cherry picked from commit 8486837842cd6779918520a17ca7c48441fe493b)
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index 21fe644..d6604a7 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -708,6 +708,7 @@ disk_monitoring_thread(void *nothing)
PRInt64 previous_mark = 0;
PRInt64 disk_space = 0;
PRInt64 threshold = 0;
+ PRInt64 halfway = 0;
time_t start = 0;
time_t now = 0;
int deleted_rotated_logs = 0;
@@ -719,7 +720,6 @@ disk_monitoring_thread(void *nothing)
int logs_disabled = 0;
int grace_period = 0;
int first_pass = 1;
- int halfway = 0;
int ok_now = 0;
while(!g_get_shutdown()) {
@@ -812,13 +812,11 @@ disk_monitoring_thread(void *nothing)
* access/audit logs, log another error, and continue.
*/
if(!logs_disabled && !logging_critical){
- if(disk_space < previous_mark){
LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %d Kb, "
"disabling access and audit logging.\n", dirstr, (disk_space / 1024), 0);
config_set_accesslog_enabled(LOGGING_OFF);
config_set_auditlog_enabled(LOGGING_OFF);
logs_disabled = 1;
- }
continue;
}
/*
@@ -826,12 +824,10 @@ disk_monitoring_thread(void *nothing)
* access/audit logging, then delete the rotated logs, log another error, and continue.
*/
if(!deleted_rotated_logs && !logging_critical){
- if(disk_space < previous_mark){
LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %d Kb, "
"deleting rotated logs.\n", dirstr, (disk_space / 1024), 0);
log__delete_rotated_logs();
deleted_rotated_logs = 1;
- }
continue;
}
/*
10 years, 10 months
Branch '389-ds-base-1.3.0' - ldap/servers
by Mark Reynolds
ldap/servers/slapd/daemon.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
New commits:
commit 49ed254f3f18bb188cd09e76bbcd834ad48c67ff
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Wed Jul 10 11:53:15 2013 -0400
Ticket 47385 - Disk Monitoring is not triggered as expected.
Bug Description: Is using large values for the threshold the faeture does not
work.
Fix Description: There was an overflow of a integer value uses to determine
if the server should enter the "shutdown mode". Also removed
some unnecessary checks to see if disk space is continuing to drop.
https://fedorahosted.org/389/ticket/47385
Reviewed by: Noriko(Thanks!)
(cherry picked from commit 8486837842cd6779918520a17ca7c48441fe493b)
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index d6ed7fa..4fbfd9d 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -710,6 +710,7 @@ disk_monitoring_thread(void *nothing)
PRInt64 previous_mark = 0;
PRInt64 disk_space = 0;
PRInt64 threshold = 0;
+ PRInt64 halfway = 0;
time_t start = 0;
time_t now = 0;
int deleted_rotated_logs = 0;
@@ -721,7 +722,6 @@ disk_monitoring_thread(void *nothing)
int logs_disabled = 0;
int grace_period = 0;
int first_pass = 1;
- int halfway = 0;
int ok_now = 0;
while(!g_get_shutdown()) {
@@ -814,13 +814,11 @@ disk_monitoring_thread(void *nothing)
* access/audit logs, log another error, and continue.
*/
if(!logs_disabled && !logging_critical){
- if(disk_space < previous_mark){
LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %d Kb, "
"disabling access and audit logging.\n", dirstr, (disk_space / 1024), 0);
config_set_accesslog_enabled(LOGGING_OFF);
config_set_auditlog_enabled(LOGGING_OFF);
logs_disabled = 1;
- }
continue;
}
/*
@@ -828,12 +826,10 @@ disk_monitoring_thread(void *nothing)
* access/audit logging, then delete the rotated logs, log another error, and continue.
*/
if(!deleted_rotated_logs && !logging_critical){
- if(disk_space < previous_mark){
LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %d Kb, "
"deleting rotated logs.\n", dirstr, (disk_space / 1024), 0);
log__delete_rotated_logs();
deleted_rotated_logs = 1;
- }
continue;
}
/*
10 years, 10 months
Branch '389-ds-base-1.3.1' - ldap/servers
by Mark Reynolds
ldap/servers/slapd/daemon.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
New commits:
commit ad8f9085916c56d0a028c5e8f8450f87b5d0f6cc
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Wed Jul 10 11:53:15 2013 -0400
Ticket 47385 - Disk Monitoring is not triggered as expected.
Bug Description: Is using large values for the threshold the faeture does not
work.
Fix Description: There was an overflow of a integer value uses to determine
if the server should enter the "shutdown mode". Also removed
some unnecessary checks to see if disk space is continuing to drop.
https://fedorahosted.org/389/ticket/47385
Reviewed by: Noriko(Thanks!)
(cherry picked from commit 8486837842cd6779918520a17ca7c48441fe493b)
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index ea31e30..6c8792f 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -710,6 +710,7 @@ disk_monitoring_thread(void *nothing)
PRInt64 previous_mark = 0;
PRInt64 disk_space = 0;
PRInt64 threshold = 0;
+ PRInt64 halfway = 0;
time_t start = 0;
time_t now = 0;
int deleted_rotated_logs = 0;
@@ -721,7 +722,6 @@ disk_monitoring_thread(void *nothing)
int logs_disabled = 0;
int grace_period = 0;
int first_pass = 1;
- int halfway = 0;
int ok_now = 0;
while(!g_get_shutdown()) {
@@ -814,13 +814,11 @@ disk_monitoring_thread(void *nothing)
* access/audit logs, log another error, and continue.
*/
if(!logs_disabled && !logging_critical){
- if(disk_space < previous_mark){
LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %d Kb, "
"disabling access and audit logging.\n", dirstr, (disk_space / 1024), 0);
config_set_accesslog_enabled(LOGGING_OFF);
config_set_auditlog_enabled(LOGGING_OFF);
logs_disabled = 1;
- }
continue;
}
/*
@@ -828,12 +826,10 @@ disk_monitoring_thread(void *nothing)
* access/audit logging, then delete the rotated logs, log another error, and continue.
*/
if(!deleted_rotated_logs && !logging_critical){
- if(disk_space < previous_mark){
LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %d Kb, "
"deleting rotated logs.\n", dirstr, (disk_space / 1024), 0);
log__delete_rotated_logs();
deleted_rotated_logs = 1;
- }
continue;
}
/*
10 years, 10 months