Branch '389-ds-base-1.3.2' - ldap/servers
by Richard Allen Megginson
ldap/servers/slapd/ldaputil.c | 51 +++---------------------------------------
1 file changed, 4 insertions(+), 47 deletions(-)
New commits:
commit 6b16d306cf64d66e10d1fa4a33a8997c3ebb5a5e
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Tue Nov 12 12:54:59 2013 -0700
Revert "Ticket #47559 hung server - related to sasl and initialize"
This reverts commit 7b3b2fe9d4a7f73a12b4f2d499b2e6a2f80e454b.
diff --git a/ldap/servers/slapd/ldaputil.c b/ldap/servers/slapd/ldaputil.c
index 32c05ec..ed3491e 100644
--- a/ldap/servers/slapd/ldaputil.c
+++ b/ldap/servers/slapd/ldaputil.c
@@ -99,16 +99,10 @@
#if !defined(USE_OPENLDAP)
#include <ldap_ssl.h>
#include <ldappr.h>
-#define BIND_LOCK (void)0
-#define BIND_UNLOCK (void)0
#else
/* need mutex around ldap_initialize - see https://fedorahosted.org/389/ticket/348 */
static PRCallOnceType ol_init_callOnce = {0,0};
static PRLock *ol_init_lock = NULL;
-/* need mutex around ldap_sasl_bind - see https://fedorahosted.org/389/ticket/47599 */
-static PRLock *ol_bind_lock = NULL;
-#define BIND_LOCK PR_Lock(ol_bind_lock)
-#define BIND_UNLOCK PR_Unlock(ol_bind_lock)
static PRStatus
internal_ol_init_init(void)
@@ -116,20 +110,12 @@ internal_ol_init_init(void)
PR_ASSERT(NULL == ol_init_lock);
if ((ol_init_lock = PR_NewLock()) == NULL) {
PRErrorCode errorCode = PR_GetError();
- slapi_log_error(SLAPI_LOG_FATAL, "internal_ol_init_init", "PR_NewLock init_lock failed %d:%s\n",
+ slapi_log_error(SLAPI_LOG_FATAL, "internal_ol_init_init", "PR_NewLock failed %d:%s\n",
errorCode, slapd_pr_strerror(errorCode));
return PR_FAILURE;
}
- PR_ASSERT(NULL == ol_bind_lock);
- if ((ol_bind_lock = PR_NewLock()) == NULL) {
- PRErrorCode errorCode = PR_GetError();
- slapi_log_error(SLAPI_LOG_FATAL, "internal_ol_init_init", "PR_NewLock bind_lock failed %d:%s\n",
- errorCode, slapd_pr_strerror(errorCode));
- return PR_FAILURE;
- }
-
- return PR_SUCCESS;
+ return PR_SUCCESS;
}
#endif
@@ -159,16 +145,7 @@ void
slapi_ldap_unbind( LDAP *ld )
{
if ( ld != NULL ) {
-#if defined(USE_OPENLDAP)
- if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
- slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_unbind",
- "Could not perform internal ol_init init\n");
- return;
- }
-#endif
- BIND_LOCK;
ldap_unbind_ext( ld, NULL, NULL );
- BIND_UNLOCK;
}
}
@@ -1057,22 +1034,11 @@ slapi_ldap_bind(
ldap_controls_free(clientctrls);
ldap_set_option(ld, LDAP_OPT_CLIENT_CONTROLS, NULL);
-#if defined(USE_OPENLDAP)
- if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
- slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
- "Could not perform internal ol_init init\n");
- rc = -1;
- goto done;
- }
-#endif
-
if ((secure > 0) && mech && !strcmp(mech, LDAP_SASL_EXTERNAL)) {
#if defined(USE_OPENLDAP)
/* we already set up a tls context in slapi_ldap_init_ext() - this will
free those old settings and context and create a new one */
- PR_Lock(ol_bind_lock);
rc = setup_ol_tls_conn(ld, 1);
- PR_Unlock(ol_bind_lock);
#else
/* SSL connections will use the server's security context
and cert for client auth */
@@ -1097,9 +1063,7 @@ slapi_ldap_bind(
}
if (secure == 2) { /* send start tls */
- BIND_LOCK;
rc = ldap_start_tls_s(ld, NULL /* serverctrls?? */, NULL);
- BIND_UNLOCK;
if (LDAP_SUCCESS != rc) {
slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
"Error: could not send startTLS request: "
@@ -1121,11 +1085,8 @@ slapi_ldap_bind(
"attempting %s bind with id [%s] creds [%s]\n",
mech ? mech : "SIMPLE",
bindid, creds);
- BIND_LOCK;
- rc = ldap_sasl_bind(ld, bindid, mech, &bvcreds, serverctrls,
- NULL /* clientctrls */, &mymsgid);
- BIND_UNLOCK;
- if (rc) {
+ if ((rc = ldap_sasl_bind(ld, bindid, mech, &bvcreds, serverctrls,
+ NULL /* clientctrls */, &mymsgid))) {
char *myhostname = NULL;
char *copy = NULL;
char *ptr = NULL;
@@ -1181,9 +1142,7 @@ slapi_ldap_bind(
/* take the one provided by the caller. It should be the one defined in the protocol */
bind_timeout = timeout;
}
- BIND_LOCK;
rc = ldap_result(ld, mymsgid, LDAP_MSG_ALL, bind_timeout, &result);
- BIND_UNLOCK;
if (-1 == rc) { /* error */
rc = slapi_ldap_get_lderrno(ld, NULL, NULL);
slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
@@ -1247,11 +1206,9 @@ slapi_ldap_bind(
ldap_set_option(ld, LDAP_OPT_X_SASL_SSF_MAX, &max_ssf);
}
#endif
- BIND_LOCK;
rc = slapd_ldap_sasl_interactive_bind(ld, bindid, creds, mech,
serverctrls, returnedctrls,
msgidp);
- BIND_UNLOCK;
if (LDAP_SUCCESS != rc) {
slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
"Error: could not perform interactive bind for id "
10 years, 5 months
ldap/servers
by Richard Allen Megginson
ldap/servers/slapd/ldaputil.c | 51 +++---------------------------------------
1 file changed, 4 insertions(+), 47 deletions(-)
New commits:
commit 941b7702bc75cea0b88ce44688d6423478be3a00
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Mon Nov 11 16:09:37 2013 -0700
Revert "Ticket #47559 hung server - related to sasl and initialize"
This reverts commit da3e4aa40b04094d0e77052b894b0f0c335ea1ef.
Did not fix the problem, and made it worse in some cases
diff --git a/ldap/servers/slapd/ldaputil.c b/ldap/servers/slapd/ldaputil.c
index e687802..6e559ee 100644
--- a/ldap/servers/slapd/ldaputil.c
+++ b/ldap/servers/slapd/ldaputil.c
@@ -99,16 +99,10 @@
#if !defined(USE_OPENLDAP)
#include <ldap_ssl.h>
#include <ldappr.h>
-#define BIND_LOCK (void)0
-#define BIND_UNLOCK (void)0
#else
/* need mutex around ldap_initialize - see https://fedorahosted.org/389/ticket/348 */
static PRCallOnceType ol_init_callOnce = {0,0};
static PRLock *ol_init_lock = NULL;
-/* need mutex around ldap_sasl_bind - see https://fedorahosted.org/389/ticket/47599 */
-static PRLock *ol_bind_lock = NULL;
-#define BIND_LOCK PR_Lock(ol_bind_lock)
-#define BIND_UNLOCK PR_Unlock(ol_bind_lock)
static PRStatus
internal_ol_init_init(void)
@@ -116,20 +110,12 @@ internal_ol_init_init(void)
PR_ASSERT(NULL == ol_init_lock);
if ((ol_init_lock = PR_NewLock()) == NULL) {
PRErrorCode errorCode = PR_GetError();
- slapi_log_error(SLAPI_LOG_FATAL, "internal_ol_init_init", "PR_NewLock init_lock failed %d:%s\n",
+ slapi_log_error(SLAPI_LOG_FATAL, "internal_ol_init_init", "PR_NewLock failed %d:%s\n",
errorCode, slapd_pr_strerror(errorCode));
return PR_FAILURE;
}
- PR_ASSERT(NULL == ol_bind_lock);
- if ((ol_bind_lock = PR_NewLock()) == NULL) {
- PRErrorCode errorCode = PR_GetError();
- slapi_log_error(SLAPI_LOG_FATAL, "internal_ol_init_init", "PR_NewLock bind_lock failed %d:%s\n",
- errorCode, slapd_pr_strerror(errorCode));
- return PR_FAILURE;
- }
-
- return PR_SUCCESS;
+ return PR_SUCCESS;
}
#endif
@@ -159,16 +145,7 @@ void
slapi_ldap_unbind( LDAP *ld )
{
if ( ld != NULL ) {
-#if defined(USE_OPENLDAP)
- if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
- slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_unbind",
- "Could not perform internal ol_init init\n");
- return;
- }
-#endif
- BIND_LOCK;
ldap_unbind_ext( ld, NULL, NULL );
- BIND_UNLOCK;
}
}
@@ -1087,22 +1064,11 @@ slapi_ldap_bind(
ldap_controls_free(clientctrls);
ldap_set_option(ld, LDAP_OPT_CLIENT_CONTROLS, NULL);
-#if defined(USE_OPENLDAP)
- if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
- slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
- "Could not perform internal ol_init init\n");
- rc = -1;
- goto done;
- }
-#endif
-
if ((secure > 0) && mech && !strcmp(mech, LDAP_SASL_EXTERNAL)) {
#if defined(USE_OPENLDAP)
/* we already set up a tls context in slapi_ldap_init_ext() - this will
free those old settings and context and create a new one */
- PR_Lock(ol_bind_lock);
rc = setup_ol_tls_conn(ld, 1);
- PR_Unlock(ol_bind_lock);
#else
/* SSL connections will use the server's security context
and cert for client auth */
@@ -1127,9 +1093,7 @@ slapi_ldap_bind(
}
if (secure == 2) { /* send start tls */
- BIND_LOCK;
rc = ldap_start_tls_s(ld, NULL /* serverctrls?? */, NULL);
- BIND_UNLOCK;
if (LDAP_SUCCESS != rc) {
slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
"Error: could not send startTLS request: "
@@ -1151,11 +1115,8 @@ slapi_ldap_bind(
"attempting %s bind with id [%s] creds [%s]\n",
mech ? mech : "SIMPLE",
bindid, creds);
- BIND_LOCK;
- rc = ldap_sasl_bind(ld, bindid, mech, &bvcreds, serverctrls,
- NULL /* clientctrls */, &mymsgid);
- BIND_UNLOCK;
- if (rc) {
+ if ((rc = ldap_sasl_bind(ld, bindid, mech, &bvcreds, serverctrls,
+ NULL /* clientctrls */, &mymsgid))) {
char *myhostname = NULL;
char *copy = NULL;
char *ptr = NULL;
@@ -1211,9 +1172,7 @@ slapi_ldap_bind(
/* take the one provided by the caller. It should be the one defined in the protocol */
bind_timeout = timeout;
}
- BIND_LOCK;
rc = ldap_result(ld, mymsgid, LDAP_MSG_ALL, bind_timeout, &result);
- BIND_UNLOCK;
if (-1 == rc) { /* error */
rc = slapi_ldap_get_lderrno(ld, NULL, NULL);
slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
@@ -1277,11 +1236,9 @@ slapi_ldap_bind(
ldap_set_option(ld, LDAP_OPT_X_SASL_SSF_MAX, &max_ssf);
}
#endif
- BIND_LOCK;
rc = slapd_ldap_sasl_interactive_bind(ld, bindid, creds, mech,
serverctrls, returnedctrls,
msgidp);
- BIND_UNLOCK;
if (LDAP_SUCCESS != rc) {
slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
"Error: could not perform interactive bind for id "
10 years, 5 months
Branch '389-ds-base-1.3.0' - ldap/servers
by Richard Allen Megginson
ldap/servers/slapd/ldaputil.c | 51 +++---------------------------------------
1 file changed, 4 insertions(+), 47 deletions(-)
New commits:
commit 20b8c33a58ed3daa5567d3ba94da4c3eb93ed9ad
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Tue Nov 12 12:56:02 2013 -0700
Revert "Ticket #47559 hung server - related to sasl and initialize"
This reverts commit 9d7fab399f334a37e9a27964765a0f9ac4bd14a3.
diff --git a/ldap/servers/slapd/ldaputil.c b/ldap/servers/slapd/ldaputil.c
index b3f7baa..8e6ec8b 100644
--- a/ldap/servers/slapd/ldaputil.c
+++ b/ldap/servers/slapd/ldaputil.c
@@ -99,16 +99,10 @@
#if !defined(USE_OPENLDAP)
#include <ldap_ssl.h>
#include <ldappr.h>
-#define BIND_LOCK (void)0
-#define BIND_UNLOCK (void)0
#else
/* need mutex around ldap_initialize - see https://fedorahosted.org/389/ticket/348 */
static PRCallOnceType ol_init_callOnce = {0,0};
static PRLock *ol_init_lock = NULL;
-/* need mutex around ldap_sasl_bind - see https://fedorahosted.org/389/ticket/47599 */
-static PRLock *ol_bind_lock = NULL;
-#define BIND_LOCK PR_Lock(ol_bind_lock)
-#define BIND_UNLOCK PR_Unlock(ol_bind_lock)
static PRStatus
internal_ol_init_init(void)
@@ -116,20 +110,12 @@ internal_ol_init_init(void)
PR_ASSERT(NULL == ol_init_lock);
if ((ol_init_lock = PR_NewLock()) == NULL) {
PRErrorCode errorCode = PR_GetError();
- slapi_log_error(SLAPI_LOG_FATAL, "internal_ol_init_init", "PR_NewLock init_lock failed %d:%s\n",
+ slapi_log_error(SLAPI_LOG_FATAL, "internal_ol_init_init", "PR_NewLock failed %d:%s\n",
errorCode, slapd_pr_strerror(errorCode));
return PR_FAILURE;
}
- PR_ASSERT(NULL == ol_bind_lock);
- if ((ol_bind_lock = PR_NewLock()) == NULL) {
- PRErrorCode errorCode = PR_GetError();
- slapi_log_error(SLAPI_LOG_FATAL, "internal_ol_init_init", "PR_NewLock bind_lock failed %d:%s\n",
- errorCode, slapd_pr_strerror(errorCode));
- return PR_FAILURE;
- }
-
- return PR_SUCCESS;
+ return PR_SUCCESS;
}
#endif
@@ -159,16 +145,7 @@ void
slapi_ldap_unbind( LDAP *ld )
{
if ( ld != NULL ) {
-#if defined(USE_OPENLDAP)
- if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
- slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_unbind",
- "Could not perform internal ol_init init\n");
- return;
- }
-#endif
- BIND_LOCK;
ldap_unbind_ext( ld, NULL, NULL );
- BIND_UNLOCK;
}
}
@@ -1054,22 +1031,11 @@ slapi_ldap_bind(
ldap_controls_free(clientctrls);
ldap_set_option(ld, LDAP_OPT_CLIENT_CONTROLS, NULL);
-#if defined(USE_OPENLDAP)
- if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
- slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
- "Could not perform internal ol_init init\n");
- rc = -1;
- goto done;
- }
-#endif
-
if ((secure > 0) && mech && !strcmp(mech, LDAP_SASL_EXTERNAL)) {
#if defined(USE_OPENLDAP)
/* we already set up a tls context in slapi_ldap_init_ext() - this will
free those old settings and context and create a new one */
- PR_Lock(ol_bind_lock);
rc = setup_ol_tls_conn(ld, 1);
- PR_Unlock(ol_bind_lock);
#else
/* SSL connections will use the server's security context
and cert for client auth */
@@ -1094,9 +1060,7 @@ slapi_ldap_bind(
}
if (secure == 2) { /* send start tls */
- BIND_LOCK;
rc = ldap_start_tls_s(ld, NULL /* serverctrls?? */, NULL);
- BIND_UNLOCK;
if (LDAP_SUCCESS != rc) {
slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
"Error: could not send startTLS request: "
@@ -1118,11 +1082,8 @@ slapi_ldap_bind(
"attempting %s bind with id [%s] creds [%s]\n",
mech ? mech : "SIMPLE",
bindid, creds);
- BIND_LOCK;
- rc = ldap_sasl_bind(ld, bindid, mech, &bvcreds, serverctrls,
- NULL /* clientctrls */, &mymsgid);
- BIND_UNLOCK;
- if (rc) {
+ if ((rc = ldap_sasl_bind(ld, bindid, mech, &bvcreds, serverctrls,
+ NULL /* clientctrls */, &mymsgid))) {
char *myhostname = NULL;
char *copy = NULL;
char *ptr = NULL;
@@ -1165,9 +1126,7 @@ slapi_ldap_bind(
if (msgidp) { /* let caller process result */
*msgidp = mymsgid;
} else { /* process results */
- BIND_LOCK;
rc = ldap_result(ld, mymsgid, LDAP_MSG_ALL, timeout, &result);
- BIND_UNLOCK;
if (-1 == rc) { /* error */
rc = slapi_ldap_get_lderrno(ld, NULL, NULL);
slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
@@ -1232,11 +1191,9 @@ slapi_ldap_bind(
ldap_set_option(ld, LDAP_OPT_X_SASL_SSF_MAX, &max_ssf);
}
#endif
- BIND_LOCK;
rc = slapd_ldap_sasl_interactive_bind(ld, bindid, creds, mech,
serverctrls, returnedctrls,
msgidp);
- BIND_UNLOCK;
if (LDAP_SUCCESS != rc) {
slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
"Error: could not perform interactive bind for id "
10 years, 5 months
ldap/servers
by Mark Reynolds
ldap/servers/slapd/proto-slap.h | 2 +-
ldap/servers/slapd/schema.c | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
New commits:
commit cb54dfed19d860e3fef0890fc5946787a93b3a19
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Tue Nov 12 10:07:22 2013 -0500
Ticket 47541 - Fix Jenkins errors
Removed unused variables.
https://fedorahosted.org/389//ticket/47541
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 9487bf7..0c4702b 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -1004,7 +1004,7 @@ int slapi_reload_schema_files(char *schemadir);
void schema_free_extensions(schemaext *extensions);
schemaext *schema_copy_extensions(schemaext *extensions);
int schema_objectclasses_superset_check(struct berval **remote_schema, char *type);
-int schema_attributypes_superset_check(struct berval **remote_schema, char *type);
+int schema_attributetypes_superset_check(struct berval **remote_schema, char *type);
/*
* schemaparse.c
diff --git a/ldap/servers/slapd/schema.c b/ldap/servers/slapd/schema.c
index 1e677c9..ef85be3 100644
--- a/ldap/servers/slapd/schema.c
+++ b/ldap/servers/slapd/schema.c
@@ -6023,7 +6023,6 @@ schema_at_superset_check(struct asyntaxinfo *at_list1, struct asyntaxinfo *at_li
struct asyntaxinfo *at_1, *at_2;
char *info = NULL;
int debug_logging = 0;
- int found = 0;
int rc = 0;
if(at_list1 == NULL || at_list2 == NULL){
@@ -6071,7 +6070,9 @@ schema_at_superset_check(struct asyntaxinfo *at_list1, struct asyntaxinfo *at_li
/*
* Check some matching rules - not finished yet...
*
- if(schema_at_superset_check_mr(at_1, at_2, info)){
+ * For now, skip the matching rule check (rc is never equal to -1)
+ */
+ if(rc == -1 && schema_at_superset_check_mr(at_1, at_2, info)){
rc = 1;
if(debug_logging){
slapi_log_error(SLAPI_LOG_REPL, "schema", "%s schema attribute [%s] matching "
@@ -6081,7 +6082,6 @@ schema_at_superset_check(struct asyntaxinfo *at_list1, struct asyntaxinfo *at_li
break;
}
}
- */
} else {
rc = 1;
if(debug_logging){
@@ -6463,7 +6463,7 @@ schema_berval_to_oclist(struct berval **oc_berval)
static struct asyntaxinfo *
schema_berval_to_atlist(struct berval **at_berval)
{
- struct asyntaxinfo *at, *head = NULL, *prev, *at_list = NULL;
+ struct asyntaxinfo *at, *head = NULL, *at_list = NULL;
char errorbuf[BUFSIZ];
int schema_ds4x_compat, rc = 0, i;
10 years, 5 months
ldap/servers
by Mark Reynolds
ldap/servers/plugins/replication/repl5_connection.c | 80 +-
ldap/servers/slapd/attrsyntax.c | 86 ++-
ldap/servers/slapd/log.c | 1
ldap/servers/slapd/proto-slap.h | 3
ldap/servers/slapd/schema.c | 542 +++++++++++++++++++-
ldap/servers/slapd/schemaparse.c | 6
ldap/servers/slapd/slap.h | 3
7 files changed, 664 insertions(+), 57 deletions(-)
New commits:
commit 42221a161fd0b288b0d7be2d95e940660e015dbe
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Thu Nov 7 12:41:41 2013 -0500
Ticket 47541 - Replication of the schema may overwrite consumer 'attributetypes' even
if consumer definition is a superset
Bug Description: Need to check consumer attributetypes to make sure it doesn't get
overwritten if it is a superset.
Fix Description: First, extended the attribute syntax struct to make it a double
linked list. This allows us to easily look through all the attributeTypes.
Then check for supersets by looking at single vs multi-valued, and
syntax oid's. Matching rules are not being evalauated at this time.
https://fedorahosted.org/389/ticket/47541
Reveiwed by: rmeggins(Thanks!)
diff --git a/ldap/servers/plugins/replication/repl5_connection.c b/ldap/servers/plugins/replication/repl5_connection.c
index 4bd14a8..0e49b94 100644
--- a/ldap/servers/plugins/replication/repl5_connection.c
+++ b/ldap/servers/plugins/replication/repl5_connection.c
@@ -98,7 +98,7 @@ typedef struct repl_connection
/*** from proto-slap.h ***/
int schema_objectclasses_superset_check(struct berval **remote_schema, char *type);
-
+int schema_attributetypes_superset_check(struct berval **remote_schema, char *type);
/* Controls we add on every outbound operation */
static LDAPControl manageDSAITControl = {LDAP_CONTROL_MANAGEDSAIT, {0, ""}, '\0'};
@@ -1579,33 +1579,57 @@ conn_push_schema(Repl_Connection *conn, CSN **remotecsn)
/* Need to free the remote_schema_csn_bervals */
ber_bvecfree(remote_schema_csn_bervals);
}
- if (return_value != CONN_SCHEMA_NO_UPDATE_NEEDED) {
- struct berval **remote_schema_objectclasses_bervals;
- /* before pushing the schema do some checking */
-
- /* First objectclasses */
- return_value = conn_read_entry_attribute(conn, "cn=schema", "objectclasses", &remote_schema_objectclasses_bervals);
- if (return_value == CONN_OPERATION_SUCCESS) {
- /* Check if the consumer objectclasses are a superset of the local supplier schema */
- if (schema_objectclasses_superset_check(remote_schema_objectclasses_bervals, OC_SUPPLIER)) {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "Schema %s must not be overwritten (set replication log for additional info)\n",
- agmt_get_long_name(conn->agmt));
- return_value = CONN_OPERATION_FAILED;
- }
- } else {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "%s: Fail to retrieve the remote schema objectclasses\n",
- agmt_get_long_name(conn->agmt));
- }
-
- /* In case of success, possibly log a message */
- if (return_value == CONN_OPERATION_SUCCESS) {
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
- "Schema checking successful: ok to push the schema (%s)\n", agmt_get_long_name(conn->agmt));
- }
- }
-
+ if (return_value != CONN_SCHEMA_NO_UPDATE_NEEDED) {
+ struct berval **remote_schema_objectclasses_bervals = NULL;
+ struct berval **remote_schema_attributetypes_bervals = NULL;
+ /* before pushing the schema do some checking */
+
+ /* First objectclasses */
+ return_value = conn_read_entry_attribute(conn, "cn=schema", "objectclasses",
+ &remote_schema_objectclasses_bervals);
+ if (return_value == CONN_OPERATION_SUCCESS) {
+ /* Check if the consumer objectclasses are a superset of the local supplier schema */
+ if (schema_objectclasses_superset_check(remote_schema_objectclasses_bervals, OC_SUPPLIER)) {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+ "Schema %s must not be overwritten (set replication log for additional info)\n",
+ agmt_get_long_name(conn->agmt));
+ return_value = CONN_OPERATION_FAILED;
+ }
+ if(remote_schema_objectclasses_bervals){
+ ber_bvecfree(remote_schema_objectclasses_bervals);
+ }
+ } else {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+ "%s: Fail to retrieve the remote schema objectclasses\n",
+ agmt_get_long_name(conn->agmt));
+ }
+ if (return_value == CONN_OPERATION_SUCCESS) {
+ /* Next attribute types */
+ return_value = conn_read_entry_attribute(conn, "cn=schema", "attributetypes",
+ &remote_schema_attributetypes_bervals);
+ if (return_value == CONN_OPERATION_SUCCESS) {
+ /* Check if the consumer attributes are a superset of the local supplier schema */
+ if (schema_attributetypes_superset_check(remote_schema_attributetypes_bervals, OC_SUPPLIER)) {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+ "Schema %s must not be overwritten (set replication log for additional info)\n",
+ agmt_get_long_name(conn->agmt));
+ return_value = CONN_OPERATION_FAILED;
+ }
+ if(remote_schema_attributetypes_bervals){
+ ber_bvecfree(remote_schema_attributetypes_bervals);
+ }
+ } else {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+ "%s: Fail to retrieve the remote schema attribute types\n",
+ agmt_get_long_name(conn->agmt));
+ }
+ }
+ /* In case of success, possibly log a message */
+ if (return_value == CONN_OPERATION_SUCCESS) {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "Schema checking successful: ok to push the schema (%s)\n", agmt_get_long_name(conn->agmt));
+ }
+ }
}
}
}
diff --git a/ldap/servers/slapd/attrsyntax.c b/ldap/servers/slapd/attrsyntax.c
index 6386fbe..885d02a 100644
--- a/ldap/servers/slapd/attrsyntax.c
+++ b/ldap/servers/slapd/attrsyntax.c
@@ -58,6 +58,9 @@ static PLHashTable *oid2asi = NULL;
static Slapi_RWLock *oid2asi_lock = NULL;
static PLHashTable *internalasi = NULL;
+/* global attribute linked list */
+static asyntaxinfo *global_at = NULL;
+
/*
* This hashtable maps the name or alias of the attribute to the
* syntax info structure for that attribute. An attribute type has as
@@ -82,12 +85,20 @@ static void attr_syntax_delete_no_lock( struct asyntaxinfo *asip,
PRBool remove_from_oid_table );
static struct asyntaxinfo *attr_syntax_get_by_oid_locking_optional( const
char *oid, PRBool use_lock);
+static void attr_syntax_insert( struct asyntaxinfo *asip );
+static void attr_syntax_remove( struct asyntaxinfo *asip );
#ifdef ATTR_LDAP_DEBUG
static void attr_syntax_print();
#endif
static int attr_syntax_init(void);
+struct asyntaxinfo *
+attr_syntax_get_global_at()
+{
+ return global_at;
+}
+
void
attr_syntax_read_lock(void)
{
@@ -202,13 +213,14 @@ attr_syntax_free( struct asyntaxinfo *a )
PR_ASSERT( a->asi_refcnt == 0 );
cool_charray_free( a->asi_aliases );
- slapi_ch_free( (void**)&a->asi_name );
- slapi_ch_free( (void **)&a->asi_desc );
- slapi_ch_free( (void **)&a->asi_oid );
- slapi_ch_free( (void **)&a->asi_superior );
- slapi_ch_free( (void **)&a->asi_mr_equality );
- slapi_ch_free( (void **)&a->asi_mr_ordering );
- slapi_ch_free( (void **)&a->asi_mr_substring );
+ slapi_ch_free_string(&a->asi_name );
+ slapi_ch_free_string(&a->asi_desc );
+ slapi_ch_free_string(&a->asi_oid );
+ slapi_ch_free_string(&a->asi_superior );
+ slapi_ch_free_string(&a->asi_mr_equality );
+ slapi_ch_free_string(&a->asi_mr_ordering );
+ slapi_ch_free_string(&a->asi_mr_substring );
+ slapi_ch_free_string(&a->asi_syntax_oid);
schema_free_extensions(a->asi_extensions);
slapi_ch_free( (void **) &a );
}
@@ -380,6 +392,7 @@ attr_syntax_return_locking_optional(struct asyntaxinfo *asi, PRBool use_lock)
}
/* ref count is 0 and it's flagged for
* deletion, so it's safe to free now */
+ attr_syntax_remove(asi);
attr_syntax_free(asi);
if(use_lock) {
AS_UNLOCK_WRITE(name2asi_lock);
@@ -411,6 +424,9 @@ attr_syntax_add_by_name(struct asyntaxinfo *a, int lock)
AS_LOCK_WRITE(name2asi_lock);
}
+ /* insert the attr into the global linked list */
+ attr_syntax_insert(a);
+
PL_HashTableAdd(name2asi, a->asi_name, a);
if ( a->asi_aliases != NULL ) {
int i;
@@ -475,6 +491,7 @@ attr_syntax_delete_no_lock( struct asyntaxinfo *asi,
* then to call return. The last return will then take care of
* the free. The only way this free would happen here is if
* you return the syntax before calling delete. */
+ attr_syntax_remove(asi);
attr_syntax_free(asi);
}
}
@@ -764,10 +781,46 @@ attr_syntax_dup( struct asyntaxinfo *a )
newas->asi_mr_eq_plugin = a->asi_mr_eq_plugin;
newas->asi_mr_ord_plugin = a->asi_mr_ord_plugin;
newas->asi_mr_sub_plugin = a->asi_mr_sub_plugin;
+ newas->asi_syntax_oid = slapi_ch_strdup(a->asi_syntax_oid);
+ newas->asi_next = NULL;
+ newas->asi_prev = NULL;
return( newas );
}
+static void
+attr_syntax_insert(struct asyntaxinfo *asip )
+{
+ /* Insert at top of list */
+ asip->asi_prev = NULL;
+ asip->asi_next = global_at;
+ if(global_at){
+ global_at->asi_prev = asip;
+ global_at = asip;
+ } else {
+ global_at = asip;
+ }
+}
+
+static void
+attr_syntax_remove(struct asyntaxinfo *asip )
+{
+ struct asyntaxinfo *prev, *next;
+
+ prev = asip->asi_prev;
+ next = asip->asi_next;
+ if(prev){
+ prev->asi_next = next;
+ if(next){
+ next->asi_prev = prev;
+ }
+ } else {
+ if(next){
+ next->asi_prev = NULL;
+ }
+ global_at = next;
+ }
+}
/*
* Add a new attribute type to the schema.
@@ -918,6 +971,7 @@ attr_syntax_create(
a.asi_mr_substring = (char*)mr_substring;
a.asi_extensions = extensions;
a.asi_plugin = plugin_syntax_find( attr_syntax );
+ a.asi_syntax_oid = (char *)attr_syntax ;
a.asi_syntaxlength = syntaxlength;
/* ideally, we would report an error and fail to start if there was some problem
with the matching rule - but since this functionality is new, and we might
@@ -1503,3 +1557,21 @@ slapi_reload_internal_attr_syntax()
attr_syntax_enumerate_attrs_ext(internalasi, attr_syntax_internal_asi_add, NULL);
return rc;
}
+
+/*
+ * See if the attribute at1 is in the list of at2. Change by name, and oid(if necessary).
+ */
+struct asyntaxinfo *
+attr_syntax_find(struct asyntaxinfo *at1, struct asyntaxinfo *at2)
+{
+ struct asyntaxinfo *asi;
+
+ for(asi = at2; asi != NULL; asi = asi->asi_next){
+ if(strcasecmp(at1->asi_name, asi->asi_name) == 0 || strcmp(at1->asi_oid, asi->asi_oid) == 0){
+ /* found it */
+ return asi;
+ }
+ }
+
+ return NULL;
+}
diff --git a/ldap/servers/slapd/log.c b/ldap/servers/slapd/log.c
index a2908d6..944876c 100644
--- a/ldap/servers/slapd/log.c
+++ b/ldap/servers/slapd/log.c
@@ -2031,7 +2031,6 @@ slapi_log_error_ext(int severity, char *subsystem, char *fmt, va_list varg1, va_
int
slapi_is_loglevel_set ( const int loglevel )
{
-
return (
#ifdef _WIN32
*module_ldap_debug
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 6539f95..9487bf7 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -136,6 +136,8 @@ struct asyntaxinfo *attr_syntax_get_by_oid ( const char *oid );
struct asyntaxinfo *attr_syntax_get_by_name ( const char *name );
struct asyntaxinfo *attr_syntax_get_by_name_with_default ( const char *name );
struct asyntaxinfo *attr_syntax_get_by_name_locking_optional ( const char *name, PRBool use_lock );
+struct asyntaxinfo *attr_syntax_get_global_at();
+struct asyntaxinfo *attr_syntax_find(struct asyntaxinfo *at1, struct asyntaxinfo *at2);
/*
* Call attr_syntax_return() when you are done using a value returned
* by attr_syntax_get_by_oid() or attr_syntax_get_by_name().
@@ -1002,6 +1004,7 @@ int slapi_reload_schema_files(char *schemadir);
void schema_free_extensions(schemaext *extensions);
schemaext *schema_copy_extensions(schemaext *extensions);
int schema_objectclasses_superset_check(struct berval **remote_schema, char *type);
+int schema_attributypes_superset_check(struct berval **remote_schema, char *type);
/*
* schemaparse.c
diff --git a/ldap/servers/slapd/schema.c b/ldap/servers/slapd/schema.c
index 6fdb99f..1e677c9 100644
--- a/ldap/servers/slapd/schema.c
+++ b/ldap/servers/slapd/schema.c
@@ -145,6 +145,9 @@ static void schema_create_errormsg( char *errorbuf, size_t errorbufsize,
#else
;
#endif
+static int schema_at_superset_check(struct asyntaxinfo *at_list1, struct asyntaxinfo *at_list2, char *message);
+static int schema_at_superset_check_syntax_oids(char *oid1, char *oid2);
+static int schema_at_superset_check_mr(struct asyntaxinfo *a1, struct asyntaxinfo *a2, char *info);
static int parse_at_str(const char *input, struct asyntaxinfo **asipp, char *errorbuf, size_t errorbufsize,
PRUint32 schema_flags, int is_user_defined, int schema_ds4x_compat, int is_remote);
static int extension_is_user_defined( schemaext *extensions );
@@ -1889,13 +1892,34 @@ modify_schema_dse (Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry *entr
rc = SLAPI_DSE_CALLBACK_ERROR;
} else {
if (strcasecmp (mods[i]->mod_type, "attributetypes") == 0) {
- /*
- * Replace all attribute types
- */
- *returncode = schema_replace_attributes( pb, mods[i], returntext,
- SLAPI_DSE_RETURNTEXT_SIZE );
+ if (is_replicated_operation) {
+ /*
+ * before accepting the schema checks if the local consumer schema is not
+ * a superset of the supplier schema
+ */
+ if (schema_attributetypes_superset_check(mods[i]->mod_bvalues, OC_CONSUMER)) {
+ schema_create_errormsg( returntext, SLAPI_DSE_RETURNTEXT_SIZE,
+ schema_errprefix_generic, mods[i]->mod_type,
+ "Replace is not possible, local consumer schema is a superset of the supplier" );
+ slapi_log_error(SLAPI_LOG_FATAL, "schema",
+ "Local %s must not be overwritten (set replication log for additional info)\n",
+ mods[i]->mod_type);
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
+ } else {
+ /*
+ * Replace all attributes
+ */
+ *returncode = schema_replace_attributes( pb, mods[i], returntext,
+ SLAPI_DSE_RETURNTEXT_SIZE );
+ }
+ } else {
+ /*
+ * Replace all objectclasses
+ */
+ *returncode = schema_replace_attributes( pb, mods[i], returntext,
+ SLAPI_DSE_RETURNTEXT_SIZE );
+ }
} else if (strcasecmp (mods[i]->mod_type, "objectclasses") == 0) {
-
if (is_replicated_operation) {
/* before accepting the schema checks if the local consumer schema is not
* a superset of the supplier schema
@@ -5870,6 +5894,7 @@ static int
schema_oc_superset_check(struct objclass *oc_list1, struct objclass *oc_list2, char *message) {
struct objclass *oc_1, *oc_2;
char *description;
+ int debug_logging = 0;
int rc, i, j;
int found;
@@ -5882,6 +5907,11 @@ schema_oc_superset_check(struct objclass *oc_list1, struct objclass *oc_list2, c
/* by default assum oc_list1 == oc_list2 */
rc = 0;
+ /* Are we doing replication logging */
+ if(slapi_is_loglevel_set(SLAPI_LOG_REPL)){
+ debug_logging = 1;
+ }
+
/* Check if all objectclass in oc_list1
* - exists in oc_list2
* - required attributes are also required in oc_2
@@ -5903,8 +5933,12 @@ schema_oc_superset_check(struct objclass *oc_list1, struct objclass *oc_list2, c
/* The oc_1 objectclasses is supperset */
rc = 1;
-
- continue; /* we continue to check all the objectclass */
+ if(debug_logging){
+ /* we continue to check all the objectclasses so we log what is wrong */
+ continue;
+ } else {
+ break;
+ }
}
/* First check the MUST */
@@ -5933,8 +5967,12 @@ schema_oc_superset_check(struct objclass *oc_list1, struct objclass *oc_list2, c
/* The oc_1 objectclasses is supperset */
rc = 1;
-
- continue; /* we continue to check all attributes */
+ if(debug_logging){
+ /* we continue to check all attributes so we log what is wrong */
+ continue;
+ } else {
+ break;
+ }
}
}
}
@@ -5963,10 +6001,14 @@ schema_oc_superset_check(struct objclass *oc_list1, struct objclass *oc_list2, c
oc_1->oc_name,
description);
- /* The oc_1 objectclasses is supperset */
+ /* The oc_1 objectclasses is superset */
rc = 1;
-
- continue; /* we continue to check all attributes */
+ if(debug_logging){
+ /* we continue to check all attributes so we log what is wrong */
+ continue;
+ } else {
+ break;
+ }
}
}
}
@@ -5975,6 +6017,385 @@ schema_oc_superset_check(struct objclass *oc_list1, struct objclass *oc_list2, c
return rc;
}
+static int
+schema_at_superset_check(struct asyntaxinfo *at_list1, struct asyntaxinfo *at_list2, char *message)
+{
+ struct asyntaxinfo *at_1, *at_2;
+ char *info = NULL;
+ int debug_logging = 0;
+ int found = 0;
+ int rc = 0;
+
+ if(at_list1 == NULL || at_list2 == NULL){
+ return 0;
+ }
+
+ /* Are we doing replication logging */
+ if(slapi_is_loglevel_set(SLAPI_LOG_REPL)){
+ debug_logging = 1;
+ }
+
+ for (at_1 = at_list1; at_1 != NULL; at_1 = at_1->asi_next){
+
+ /* check if at_1 exists in at_list2 */
+ if((at_2 = attr_syntax_find(at_1, at_list2))){
+ /*
+ * Check for single vs. multi value
+ */
+ if(!(at_1->asi_flags & SLAPI_ATTR_FLAG_SINGLE) && (at_2->asi_flags & SLAPI_ATTR_FLAG_SINGLE)){
+ /* at_list 1 is a superset */
+ rc = 1;
+ if(debug_logging){
+ slapi_log_error(SLAPI_LOG_REPL, "schema", "%s schema attribute [%s] is not "
+ "\"single-valued\" \n",message, at_1->asi_name);
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ /*
+ * Check the syntaxes
+ */
+ if(schema_at_superset_check_syntax_oids(at_1->asi_syntax_oid, at_2->asi_syntax_oid)){
+ /* at_list 1 is a superset */
+ rc = 1;
+ if(debug_logging){
+ slapi_log_error(SLAPI_LOG_REPL, "schema", "%s schema attribute [%s] syntax "
+ "can not be overwritten\n",message, at_1->asi_name);
+ continue;
+ } else {
+ break;
+ }
+ }
+ /*
+ * Check some matching rules - not finished yet...
+ *
+ if(schema_at_superset_check_mr(at_1, at_2, info)){
+ rc = 1;
+ if(debug_logging){
+ slapi_log_error(SLAPI_LOG_REPL, "schema", "%s schema attribute [%s] matching "
+ "rule can not be overwritten\n",message, at_1->asi_name);
+ continue;
+ } else {
+ break;
+ }
+ }
+ */
+ } else {
+ rc = 1;
+ if(debug_logging){
+ /* we continue to check all attributes so we log what is wrong */
+ slapi_log_error(SLAPI_LOG_REPL, "schema", "Fail to retrieve in the %s schema [%s or %s]\n",
+ message, at_1->asi_name, at_1->asi_oid);
+ continue;
+ } else {
+ break;
+ }
+ }
+ }
+
+
+ return rc;
+}
+
+/*
+ * Return 1 if a1's matching rules are superset(not to be overwritten). If just one of
+ * the matching rules should not be overwritten, even if one should, we can not allow it.
+ */
+static int
+schema_at_superset_check_mr(struct asyntaxinfo *a1, struct asyntaxinfo *a2, char *info)
+{
+ char *a1_mrtype[3] = { a1->asi_mr_equality, a1->asi_mr_substring, a1->asi_mr_ordering };
+ char *a2_mrtype[3] = { a2->asi_mr_equality, a2->asi_mr_substring, a2->asi_mr_ordering };
+ int rc = 0, i;
+
+ /*
+ * Loop over the three matching rule types
+ */
+ for(i = 0; i < 3; i++){
+ if(a1_mrtype[i]){
+ if(a2_mrtype[i]){
+ /*
+ * Future action item - determine matching rule precedence:
+ *
+ ces
+ "caseExactIA5Match", "1.3.6.1.4.1.1466.109.114.1"
+ "caseExactMatch", "2.5.13.5"
+ "caseExactOrderingMatch", "2.5.13.6"
+ "caseExactSubstringsMatch", "2.5.13.7"
+ "caseExactIA5SubstringsMatch", "2.16.840.1.113730.3.3.1"
+
+ cis
+ "generalizedTimeMatch", "2.5.13.27"
+ "generalizedTimeOrderingMatch", "2.5.13.28"
+ "booleanMatch", "2.5.13.13"
+ "caseIgnoreIA5Match", "1.3.6.1.4.1.1466.109.114.2"
+ "caseIgnoreIA5SubstringsMatch", "1.3.6.1.4.1.1466.109.114.3"
+ "caseIgnoreListMatch", "2.5.13.11"
+ "caseIgnoreListSubstringsMatch", "2.5.13.12"
+ "caseIgnoreMatch", "2.5.13.2" -------------------------------
+ "caseIgnoreOrderingMatch", "2.5.13.3" -----------------------> can have lang options
+ "caseIgnoreSubstringsMatch", "2.5.13.4" --------------------- (as seen in the console)!
+ "directoryStringFirstComponentMatch", "2.5.13.31"
+ "objectIdentifierMatch", "2.5.13.0"
+ "objectIdentifierFirstComponentMatch", "2.5.13.30"
+
+ bitstring
+ "bitStringMatch", "2.5.13.16","2.16.840.1.113730.3.3.1"
+
+ bin
+ "octetStringMatch", "2.5.13.17"
+ "octetStringOrderingMatch", "2.5.13.18"
+
+ DN
+ "distinguishedNameMatch", "2.5.13.1"
+
+ Int
+ "integerMatch", "2.5.13.14"
+ "integerOrderingMatch", "2.5.13.15"
+ "integerFirstComponentMatch", "2.5.13.29"
+
+ NameAndOptUID
+ "uniqueMemberMatch", "2.5.13.23"
+
+ NumericString
+ "numericStringMatch", "2.5.13.8"
+ "numericStringOrderingMatch", "2.5.13.9"
+ "numericStringSubstringsMatch", "2.5.13.10"
+
+ Telephone
+ "telephoneNumberMatch", "2.5.13.20"
+ "telephoneNumberSubstringsMatch", "2.5.13.21"
+ */
+ }
+ }
+ }
+
+ return rc;
+}
+
+/*
+ * Return 1 if oid1 is a superset(oid1 is not to be overwritten)
+ */
+static int
+schema_at_superset_check_syntax_oids(char *oid1, char *oid2)
+{
+ if(oid1 == NULL && oid2 == NULL){
+ return 0;
+ } else if (oid2 == NULL){
+ return 0;
+ } else if (oid1 == NULL){
+ return 1;
+ }
+
+ if(strcmp(oid1, BINARY_SYNTAX_OID) == 0){
+ if(strcmp(oid2, BINARY_SYNTAX_OID) &&
+ strcmp(oid2, INTEGER_SYNTAX_OID) &&
+ strcmp(oid2, NUMERICSTRING_SYNTAX_OID) &&
+ strcmp(oid2, IA5STRING_SYNTAX_OID) &&
+ strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
+ strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
+ strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
+ strcmp(oid2, FACSIMILE_SYNTAX_OID) &&
+ strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
+ strcmp(oid2, TELEPHONE_SYNTAX_OID) &&
+ strcmp(oid2, TELETEXTERMID_SYNTAX_OID) &&
+ strcmp(oid2, TELEXNUMBER_SYNTAX_OID))
+
+ {
+ return 1;
+ }
+ } else if(strcmp(oid1, BITSTRING_SYNTAX_OID) == 0){
+ if(strcmp(oid2, BINARY_SYNTAX_OID) &&
+ strcmp(oid2, BITSTRING_SYNTAX_OID) &&
+ strcmp(oid2, INTEGER_SYNTAX_OID) &&
+ strcmp(oid2, NUMERICSTRING_SYNTAX_OID) &&
+ strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
+ strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
+ strcmp(oid2, IA5STRING_SYNTAX_OID) &&
+ strcmp(oid2, FACSIMILE_SYNTAX_OID) &&
+ strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
+ strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
+ strcmp(oid2, TELEPHONE_SYNTAX_OID) &&
+ strcmp(oid2, TELETEXTERMID_SYNTAX_OID) &&
+ strcmp(oid2, TELEXNUMBER_SYNTAX_OID))
+ {
+ return 1;
+ }
+ } else if(strcmp(oid1, BOOLEAN_SYNTAX_OID) == 0){
+ if(strcmp(oid2, BOOLEAN_SYNTAX_OID) &&
+ strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
+ strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
+ strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
+ strcmp(oid2, IA5STRING_SYNTAX_OID))
+ {
+ return 1;
+ }
+ } else if(strcmp(oid1, COUNTRYSTRING_SYNTAX_OID) ==0){
+ if(strcmp(oid2, COUNTRYSTRING_SYNTAX_OID) &&
+ strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
+ strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
+ strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
+ strcmp(oid2, IA5STRING_SYNTAX_OID))
+ {
+ return 1;
+ }
+ } else if(strcmp(oid1, DN_SYNTAX_OID) == 0){
+ if(strcmp(oid2, DN_SYNTAX_OID) &&
+ strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
+ strcmp(oid2, DIRSTRING_SYNTAX_OID) )
+ {
+ return 1;
+ }
+ } else if(strcmp(oid1, DELIVERYMETHOD_SYNTAX_OID) ==0){
+ if(strcmp(oid2, DELIVERYMETHOD_SYNTAX_OID) &&
+ strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
+ strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
+ strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
+ strcmp(oid2, IA5STRING_SYNTAX_OID))
+ {
+ return 1;
+ }
+ } else if(strcmp(oid1, DIRSTRING_SYNTAX_OID) == 0){
+ if(strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
+ strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID)){
+ return 1;
+ }
+ } else if(strcmp(oid1, ENHANCEDGUIDE_SYNTAX_OID) == 0){
+ if(strcmp(oid2, ENHANCEDGUIDE_SYNTAX_OID) &&
+ strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
+ strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
+ strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
+ strcmp(oid2, IA5STRING_SYNTAX_OID))
+ {
+ return 1;
+ }
+ } else if(strcmp(oid1, IA5STRING_SYNTAX_OID) == 0){
+ if(strcmp(oid2, IA5STRING_SYNTAX_OID) &&
+ strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
+ strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
+ strcmp(oid2, PRINTABLESTRING_SYNTAX_OID))
+ {
+ return 1;
+ }
+ } else if(strcmp(oid1, INTEGER_SYNTAX_OID) == 0){
+ if(strcmp(oid2, INTEGER_SYNTAX_OID) &&
+ strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
+ strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
+ strcmp(oid2, NUMERICSTRING_SYNTAX_OID) &&
+ strcmp(oid2, TELEPHONE_SYNTAX_OID) &&
+ strcmp(oid2, TELETEXTERMID_SYNTAX_OID) &&
+ strcmp(oid2, TELEXNUMBER_SYNTAX_OID) &&
+ strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
+ strcmp(oid2, IA5STRING_SYNTAX_OID) )
+ {
+ return 1;
+ }
+ } else if(strcmp(oid1, JPEG_SYNTAX_OID) == 0){
+ if(strcmp(oid2, JPEG_SYNTAX_OID) &&
+ strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
+ strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
+ strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
+ strcmp(oid2, IA5STRING_SYNTAX_OID))
+ {
+ return 1;
+ }
+ } else if(strcmp(oid1, NAMEANDOPTIONALUID_SYNTAX_OID) == 0){
+ if(strcmp(oid2, NAMEANDOPTIONALUID_SYNTAX_OID) &&
+ strcmp(oid2, NAMEANDOPTIONALUID_SYNTAX_OID) &&
+ strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
+ strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
+ strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
+ strcmp(oid2, IA5STRING_SYNTAX_OID))
+ {
+ return 1;
+ }
+ } else if(strcmp(oid1, NUMERICSTRING_SYNTAX_OID) == 0){
+ if(strcmp(oid2, NUMERICSTRING_SYNTAX_OID) &&
+ strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
+ strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
+ strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
+ strcmp(oid2, IA5STRING_SYNTAX_OID))
+ {
+ return 1;
+ }
+ } else if(strcmp(oid1, OID_SYNTAX_OID) == 0){
+ if(strcmp(oid2, OID_SYNTAX_OID) &&
+ strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
+ strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
+ strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
+ strcmp(oid2, IA5STRING_SYNTAX_OID))
+ {
+ return 1;
+ }
+ } else if (strcmp(oid1, OCTETSTRING_SYNTAX_OID) == 0){
+ if(strcmp(oid2, OCTETSTRING_SYNTAX_OID) &&
+ strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
+ strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
+ strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
+ strcmp(oid2, IA5STRING_SYNTAX_OID))
+ {
+ return 1;
+ }
+ } else if(strcmp(oid1, POSTALADDRESS_SYNTAX_OID) ==0){
+ if(strcmp(oid2, POSTALADDRESS_SYNTAX_OID) &&
+ strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
+ strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
+ strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
+ strcmp(oid2, IA5STRING_SYNTAX_OID))
+ {
+ return 1;
+ }
+ } else if(strcmp(oid1, PRINTABLESTRING_SYNTAX_OID) == 0){
+ if(strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
+ strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
+ strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
+ strcmp(oid2, IA5STRING_SYNTAX_OID))
+ {
+ return 1;
+ }
+ } else if(strcmp(oid1, TELEPHONE_SYNTAX_OID) == 0){
+ if(strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
+ strcmp(oid2, TELEPHONE_SYNTAX_OID) &&
+ strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
+ strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
+ strcmp(oid2, IA5STRING_SYNTAX_OID))
+ {
+ return 1;
+ }
+ } else if(strcmp(oid1, TELETEXTERMID_SYNTAX_OID) == 0){
+ if(strcmp(oid2, TELETEXTERMID_SYNTAX_OID) &&
+ strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
+ strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
+ strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
+ strcmp(oid2, IA5STRING_SYNTAX_OID))
+ {
+ return 1;
+ }
+ } else if(strcmp(oid1, TELEXNUMBER_SYNTAX_OID) == 0){
+ if(strcmp(oid2, TELEXNUMBER_SYNTAX_OID) &&
+ strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
+ strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
+ strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
+ strcmp(oid2, IA5STRING_SYNTAX_OID))
+ {
+ return 1;
+ }
+ } else if (strcmp(oid1, SPACE_INSENSITIVE_STRING_SYNTAX_OID) == 0){
+ if(strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
+ strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
+ strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
+ strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
+ strcmp(oid2, IA5STRING_SYNTAX_OID))
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
static void
schema_oclist_free(struct objclass *oc_list)
{
@@ -5986,8 +6407,20 @@ schema_oclist_free(struct objclass *oc_list)
}
}
-static
-struct objclass *schema_berval_to_oclist(struct berval **oc_berval) {
+static void
+schema_atlist_free(struct asyntaxinfo *at_list)
+{
+ struct asyntaxinfo *at, *at_next;
+
+ for (at = at_list; at != NULL; at = at_next) {
+ at_next = at->asi_next;
+ attr_syntax_free(at);
+ }
+}
+
+static struct objclass *
+schema_berval_to_oclist(struct berval **oc_berval)
+{
struct objclass *oc, *oc_list, *oc_tail;
char errorbuf[BUFSIZ];
int schema_ds4x_compat, rc;
@@ -6027,8 +6460,43 @@ struct objclass *schema_berval_to_oclist(struct berval **oc_berval) {
return oc_list;
}
+static struct asyntaxinfo *
+schema_berval_to_atlist(struct berval **at_berval)
+{
+ struct asyntaxinfo *at, *head = NULL, *prev, *at_list = NULL;
+ char errorbuf[BUFSIZ];
+ int schema_ds4x_compat, rc = 0, i;
+
+ schema_ds4x_compat = config_get_ds4_compatible_schema();
+
+ if (at_berval != NULL) {
+ for (i = 0; at_berval[i] != NULL; i++) {
+ /* parse the objectclass value */
+ rc = parse_at_str(at_berval[i]->bv_val, &at, errorbuf, sizeof (errorbuf),
+ DSE_SCHEMA_NO_CHECK | DSE_SCHEMA_USE_PRIV_SCHEMA, 0, schema_ds4x_compat, 0);
+ if(rc){
+ attr_syntax_free(at);
+ break;
+ }
+ if(!head){
+ head = at_list = at;
+ } else {
+ at_list->asi_next = at;
+ at->asi_prev = at_list;
+ at_list = at;
+ }
+ }
+ }
+ if (rc) {
+ schema_atlist_free(head);
+ }
+
+ return head;
+}
+
int
-schema_objectclasses_superset_check(struct berval **remote_schema, char *type) {
+schema_objectclasses_superset_check(struct berval **remote_schema, char *type)
+{
int rc;
struct objclass *remote_oc_list;
@@ -6072,3 +6540,45 @@ schema_objectclasses_superset_check(struct berval **remote_schema, char *type) {
}
return rc;
}
+
+int
+schema_attributetypes_superset_check(struct berval **remote_schema, char *type)
+{
+ struct asyntaxinfo *remote_at_list = NULL;
+ int rc = 0;
+
+ if (remote_schema != NULL) {
+ /* First build an attribute list from the remote schema */
+ if ((remote_at_list = schema_berval_to_atlist(remote_schema)) == NULL) {
+ rc = 1;
+ return rc;
+ }
+
+ /*
+ * Check that for each object from the remote schema
+ * - MUST attributes are also MUST in local schema
+ * - ALLOWED attributes are also ALLOWED in local schema
+ */
+ if (remote_at_list) {
+ attr_syntax_read_lock();
+ if (strcmp(type, OC_SUPPLIER) == 0) {
+ /*
+ * Check if the remote_at_list from a consumer are or not
+ * a superset of the attributetypes of the local supplier schema
+ */
+ rc = schema_at_superset_check(remote_at_list, attr_syntax_get_global_at(), "local supplier" );
+ } else {
+ /*
+ * Check if the attributeypes of the local consumer schema are or not
+ * a superset of the remote_at_list from a supplier
+ */
+ rc = schema_at_superset_check(attr_syntax_get_global_at(), remote_at_list, "remote supplier");
+ }
+ attr_syntax_unlock_read();
+ }
+
+ /* Free the remote schema list */
+ schema_atlist_free(remote_at_list);
+ }
+ return rc;
+}
diff --git a/ldap/servers/slapd/schemaparse.c b/ldap/servers/slapd/schemaparse.c
index eb68f88..9636be5 100644
--- a/ldap/servers/slapd/schemaparse.c
+++ b/ldap/servers/slapd/schemaparse.c
@@ -51,15 +51,11 @@
/* global_oc and global_schema_csn are both protected by oc locks */
struct objclass *global_oc;
CSN *global_schema_csn = NULL; /* Timestamp for last update CSN. NULL = epoch */
+static Slapi_RWLock *oc_lock = NULL;
static int is_duplicate( char *target, char **list, int list_max );
static void normalize_list( char **list );
-
-
-/* R/W lock used to protect the global objclass linked list. */
-static Slapi_RWLock *oc_lock = NULL;
-
/*
* The oc_init_lock_callonce structure is used by NSPR to ensure
* that oc_init_lock() is called at most once.
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index ffee433..3513cfd 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -517,6 +517,7 @@ typedef struct asyntaxinfo {
char *asi_mr_substring; /* substring matching rule */
schemaext *asi_extensions; /* schema extensions (X-ORIGIN, X-?????, ...) */
struct slapdplugin *asi_plugin; /* syntax */
+ char *asi_syntax_oid; /* syntax oid */
unsigned long asi_flags; /* SLAPI_ATTR_FLAG_... */
int asi_syntaxlength; /* length associated w/syntax */
int asi_refcnt; /* outstanding references */
@@ -524,6 +525,8 @@ typedef struct asyntaxinfo {
struct slapdplugin *asi_mr_eq_plugin; /* EQUALITY matching rule plugin */
struct slapdplugin *asi_mr_sub_plugin; /* SUBSTR matching rule plugin */
struct slapdplugin *asi_mr_ord_plugin; /* ORDERING matching rule plugin */
+ struct asyntaxinfo *asi_next;
+ struct asyntaxinfo *asi_prev;
} asyntaxinfo;
/*
10 years, 5 months
ldap/servers
by Richard Allen Megginson
ldap/servers/plugins/replication/cl5_clcache.c | 48 +++++++++++++++++++++----
1 file changed, 42 insertions(+), 6 deletions(-)
New commits:
commit cf08f1274404e4796966011a98a6a0acbbfd6070
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Wed Nov 6 14:22:31 2013 -0700
Ticket #47585 Replication Failures related to skipped entries due to cleaned rids
https://fedorahosted.org/389/ticket/47585
Reviewed by: nhosoi (Thanks!)
Branch: master
Fix Description: If a change was found in the changelog buffer that is
skipped due to having an unknown replica ID (rid), the entire buffer was
marked as CLC_STATE_NEW_RID. When the buffer is exhausted and the iterator
code goes to read in the new buffer, it would not read in the new buffer
because it only loads a new buffer if the current buffer state is
CLC_STATE_READY. I don't know why the entire buffer would be marked as
CLC_STATE_NEW_RID and stop iteration. It seems to me that just the update
should be skipped, but new buffers should be loaded in order to keep sending
non-skipped updates to the consumer.
It is possible for a CSN with an unknown RID to get into the changelog if
the server with that RID had been removed by cleanruv/cleanallruv. In that
case, the CSN should be skipped. It is assumed that the change was already
sent - cleanallruv is supposed to wait until all known changes have been
seen before removing the RID from the RUV - so it is safe to skip it.
Added additional debugging, so that we can better tell why changelog entries
were skipped.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
diff --git a/ldap/servers/plugins/replication/cl5_clcache.c b/ldap/servers/plugins/replication/cl5_clcache.c
index 7a6a446..8218312 100644
--- a/ldap/servers/plugins/replication/cl5_clcache.c
+++ b/ldap/servers/plugins/replication/cl5_clcache.c
@@ -120,6 +120,11 @@ struct clc_buffer {
int buf_load_cnt; /* number of loads for session */
int buf_record_cnt; /* number of changes for session */
int buf_record_skipped; /* number of changes skipped */
+ int buf_skipped_new_rid; /* number of changes skipped due to new_rid */
+ int buf_skipped_csn_gt_cons_maxcsn; /* number of changes skipped due to csn greater than consumer maxcsn */
+ int buf_skipped_up_to_date; /* number of changes skipped due to consumer being up-to-date for the given rid */
+ int buf_skipped_csn_gt_ruv; /* number of changes skipped due to preceedents are not covered by local RUV snapshot */
+ int buf_skipped_csn_covered; /* number of changes skipped due to CSNs already covered by consumer RUV */
/*
* fields that should be accessed via bl_lock or pl_lock
@@ -252,6 +257,11 @@ clcache_get_buffer ( CLC_Buffer **buf, DB *db, ReplicaId consumer_rid, const RUV
(*buf)->buf_record_skipped = 0;
(*buf)->buf_cursor = NULL;
(*buf)->buf_num_cscbs = 0;
+ (*buf)->buf_skipped_new_rid = 0;
+ (*buf)->buf_skipped_csn_gt_cons_maxcsn = 0;
+ (*buf)->buf_skipped_up_to_date = 0;
+ (*buf)->buf_skipped_csn_gt_ruv = 0;
+ (*buf)->buf_skipped_csn_covered = 0;
}
else {
*buf = clcache_new_buffer ( consumer_rid );
@@ -287,11 +297,16 @@ clcache_return_buffer ( CLC_Buffer **buf )
int i;
slapi_log_error ( SLAPI_LOG_REPL, (*buf)->buf_agmt_name,
- "session end: state=%d load=%d sent=%d skipped=%d\n",
- (*buf)->buf_state,
- (*buf)->buf_load_cnt,
- (*buf)->buf_record_cnt - (*buf)->buf_record_skipped,
- (*buf)->buf_record_skipped );
+ "session end: state=%d load=%d sent=%d skipped=%d skipped_new_rid=%d "
+ "skipped_csn_gt_cons_maxcsn=%d skipped_up_to_date=%d "
+ "skipped_csn_gt_ruv=%d skipped_csn_covered=%d\n",
+ (*buf)->buf_state,
+ (*buf)->buf_load_cnt,
+ (*buf)->buf_record_cnt - (*buf)->buf_record_skipped,
+ (*buf)->buf_record_skipped, (*buf)->buf_skipped_new_rid,
+ (*buf)->buf_skipped_csn_gt_cons_maxcsn,
+ (*buf)->buf_skipped_up_to_date, (*buf)->buf_skipped_csn_gt_ruv,
+ (*buf)->buf_skipped_csn_covered);
for ( i = 0; i < (*buf)->buf_num_cscbs; i++ ) {
clcache_free_cscb ( &(*buf)->buf_cscbs[i] );
@@ -676,6 +691,8 @@ clcache_skip_change ( CLC_Buffer *buf )
ReplicaId rid;
int skip = 1;
int i;
+ char buf_cur_csn_str[CSN_STRSIZE];
+ char oth_csn_str[CSN_STRSIZE];
do {
@@ -697,6 +714,14 @@ clcache_skip_change ( CLC_Buffer *buf )
* The consumer must have been "restored" and needs this newer update.
*/
skip = 0;
+ } else if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) {
+ csn_as_string(buf->buf_current_csn, 0, buf_cur_csn_str);
+ csn_as_string(cons_maxcsn, 0, oth_csn_str);
+ slapi_log_error(SLAPI_LOG_REPL, buf->buf_agmt_name,
+ "Skipping update because the changelog buffer current csn [%s] is "
+ "less than or equal to the consumer max csn [%s]\n",
+ buf_cur_csn_str, oth_csn_str);
+ buf->buf_skipped_csn_gt_cons_maxcsn++;
}
csn_free(&cons_maxcsn);
break;
@@ -714,7 +739,14 @@ clcache_skip_change ( CLC_Buffer *buf )
/* Skip CSN whose RID is unknown to the local RUV snapshot */
if ( i >= buf->buf_num_cscbs ) {
- buf->buf_state = CLC_STATE_NEW_RID;
+ if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) {
+ csn_as_string(buf->buf_current_csn, 0, buf_cur_csn_str);
+ slapi_log_error(SLAPI_LOG_REPL, buf->buf_agmt_name,
+ "Skipping update because the changelog buffer current csn [%s] rid "
+ "[%d] is not in the list of changelog csn buffers (length %d)\n",
+ buf_cur_csn_str, rid, buf->buf_num_cscbs);
+ }
+ buf->buf_skipped_new_rid++;
break;
}
@@ -722,17 +754,20 @@ clcache_skip_change ( CLC_Buffer *buf )
/* Skip if the consumer is already up-to-date for the RID */
if ( cscb->state == CLC_STATE_UP_TO_DATE ) {
+ buf->buf_skipped_up_to_date++;
break;
}
/* Skip CSN whose preceedents are not covered by local RUV snapshot */
if ( cscb->state == CLC_STATE_CSN_GT_RUV ) {
+ buf->buf_skipped_csn_gt_ruv++;
break;
}
/* Skip CSNs already covered by consumer RUV */
if ( cscb->consumer_maxcsn &&
csn_compare ( buf->buf_current_csn, cscb->consumer_maxcsn ) <= 0 ) {
+ buf->buf_skipped_csn_covered++;
break;
}
@@ -762,6 +797,7 @@ clcache_skip_change ( CLC_Buffer *buf )
/* Skip CSNs not covered by local RUV snapshot */
cscb->state = CLC_STATE_CSN_GT_RUV;
+ buf->buf_skipped_csn_gt_ruv++;
} while (0);
10 years, 5 months
Branch '389-ds-base-1.3.2' - ldap/servers
by Richard Allen Megginson
ldap/servers/plugins/replication/cl5_clcache.c | 48 +++++++++++++++++++++----
1 file changed, 42 insertions(+), 6 deletions(-)
New commits:
commit 30bb98fb693ea1aac9774bdc43b923eacd72570a
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Wed Nov 6 14:22:31 2013 -0700
Ticket #47585 Replication Failures related to skipped entries due to cleaned rids
https://fedorahosted.org/389/ticket/47585
Reviewed by: nhosoi (Thanks!)
Branch: 389-ds-base-1.3.2
Fix Description: If a change was found in the changelog buffer that is
skipped due to having an unknown replica ID (rid), the entire buffer was
marked as CLC_STATE_NEW_RID. When the buffer is exhausted and the iterator
code goes to read in the new buffer, it would not read in the new buffer
because it only loads a new buffer if the current buffer state is
CLC_STATE_READY. I don't know why the entire buffer would be marked as
CLC_STATE_NEW_RID and stop iteration. It seems to me that just the update
should be skipped, but new buffers should be loaded in order to keep sending
non-skipped updates to the consumer.
It is possible for a CSN with an unknown RID to get into the changelog if
the server with that RID had been removed by cleanruv/cleanallruv. In that
case, the CSN should be skipped. It is assumed that the change was already
sent - cleanallruv is supposed to wait until all known changes have been
seen before removing the RID from the RUV - so it is safe to skip it.
Added additional debugging, so that we can better tell why changelog entries
were skipped.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
(cherry picked from commit cf08f1274404e4796966011a98a6a0acbbfd6070)
diff --git a/ldap/servers/plugins/replication/cl5_clcache.c b/ldap/servers/plugins/replication/cl5_clcache.c
index 7a6a446..8218312 100644
--- a/ldap/servers/plugins/replication/cl5_clcache.c
+++ b/ldap/servers/plugins/replication/cl5_clcache.c
@@ -120,6 +120,11 @@ struct clc_buffer {
int buf_load_cnt; /* number of loads for session */
int buf_record_cnt; /* number of changes for session */
int buf_record_skipped; /* number of changes skipped */
+ int buf_skipped_new_rid; /* number of changes skipped due to new_rid */
+ int buf_skipped_csn_gt_cons_maxcsn; /* number of changes skipped due to csn greater than consumer maxcsn */
+ int buf_skipped_up_to_date; /* number of changes skipped due to consumer being up-to-date for the given rid */
+ int buf_skipped_csn_gt_ruv; /* number of changes skipped due to preceedents are not covered by local RUV snapshot */
+ int buf_skipped_csn_covered; /* number of changes skipped due to CSNs already covered by consumer RUV */
/*
* fields that should be accessed via bl_lock or pl_lock
@@ -252,6 +257,11 @@ clcache_get_buffer ( CLC_Buffer **buf, DB *db, ReplicaId consumer_rid, const RUV
(*buf)->buf_record_skipped = 0;
(*buf)->buf_cursor = NULL;
(*buf)->buf_num_cscbs = 0;
+ (*buf)->buf_skipped_new_rid = 0;
+ (*buf)->buf_skipped_csn_gt_cons_maxcsn = 0;
+ (*buf)->buf_skipped_up_to_date = 0;
+ (*buf)->buf_skipped_csn_gt_ruv = 0;
+ (*buf)->buf_skipped_csn_covered = 0;
}
else {
*buf = clcache_new_buffer ( consumer_rid );
@@ -287,11 +297,16 @@ clcache_return_buffer ( CLC_Buffer **buf )
int i;
slapi_log_error ( SLAPI_LOG_REPL, (*buf)->buf_agmt_name,
- "session end: state=%d load=%d sent=%d skipped=%d\n",
- (*buf)->buf_state,
- (*buf)->buf_load_cnt,
- (*buf)->buf_record_cnt - (*buf)->buf_record_skipped,
- (*buf)->buf_record_skipped );
+ "session end: state=%d load=%d sent=%d skipped=%d skipped_new_rid=%d "
+ "skipped_csn_gt_cons_maxcsn=%d skipped_up_to_date=%d "
+ "skipped_csn_gt_ruv=%d skipped_csn_covered=%d\n",
+ (*buf)->buf_state,
+ (*buf)->buf_load_cnt,
+ (*buf)->buf_record_cnt - (*buf)->buf_record_skipped,
+ (*buf)->buf_record_skipped, (*buf)->buf_skipped_new_rid,
+ (*buf)->buf_skipped_csn_gt_cons_maxcsn,
+ (*buf)->buf_skipped_up_to_date, (*buf)->buf_skipped_csn_gt_ruv,
+ (*buf)->buf_skipped_csn_covered);
for ( i = 0; i < (*buf)->buf_num_cscbs; i++ ) {
clcache_free_cscb ( &(*buf)->buf_cscbs[i] );
@@ -676,6 +691,8 @@ clcache_skip_change ( CLC_Buffer *buf )
ReplicaId rid;
int skip = 1;
int i;
+ char buf_cur_csn_str[CSN_STRSIZE];
+ char oth_csn_str[CSN_STRSIZE];
do {
@@ -697,6 +714,14 @@ clcache_skip_change ( CLC_Buffer *buf )
* The consumer must have been "restored" and needs this newer update.
*/
skip = 0;
+ } else if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) {
+ csn_as_string(buf->buf_current_csn, 0, buf_cur_csn_str);
+ csn_as_string(cons_maxcsn, 0, oth_csn_str);
+ slapi_log_error(SLAPI_LOG_REPL, buf->buf_agmt_name,
+ "Skipping update because the changelog buffer current csn [%s] is "
+ "less than or equal to the consumer max csn [%s]\n",
+ buf_cur_csn_str, oth_csn_str);
+ buf->buf_skipped_csn_gt_cons_maxcsn++;
}
csn_free(&cons_maxcsn);
break;
@@ -714,7 +739,14 @@ clcache_skip_change ( CLC_Buffer *buf )
/* Skip CSN whose RID is unknown to the local RUV snapshot */
if ( i >= buf->buf_num_cscbs ) {
- buf->buf_state = CLC_STATE_NEW_RID;
+ if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) {
+ csn_as_string(buf->buf_current_csn, 0, buf_cur_csn_str);
+ slapi_log_error(SLAPI_LOG_REPL, buf->buf_agmt_name,
+ "Skipping update because the changelog buffer current csn [%s] rid "
+ "[%d] is not in the list of changelog csn buffers (length %d)\n",
+ buf_cur_csn_str, rid, buf->buf_num_cscbs);
+ }
+ buf->buf_skipped_new_rid++;
break;
}
@@ -722,17 +754,20 @@ clcache_skip_change ( CLC_Buffer *buf )
/* Skip if the consumer is already up-to-date for the RID */
if ( cscb->state == CLC_STATE_UP_TO_DATE ) {
+ buf->buf_skipped_up_to_date++;
break;
}
/* Skip CSN whose preceedents are not covered by local RUV snapshot */
if ( cscb->state == CLC_STATE_CSN_GT_RUV ) {
+ buf->buf_skipped_csn_gt_ruv++;
break;
}
/* Skip CSNs already covered by consumer RUV */
if ( cscb->consumer_maxcsn &&
csn_compare ( buf->buf_current_csn, cscb->consumer_maxcsn ) <= 0 ) {
+ buf->buf_skipped_csn_covered++;
break;
}
@@ -762,6 +797,7 @@ clcache_skip_change ( CLC_Buffer *buf )
/* Skip CSNs not covered by local RUV snapshot */
cscb->state = CLC_STATE_CSN_GT_RUV;
+ buf->buf_skipped_csn_gt_ruv++;
} while (0);
10 years, 5 months
Branch '389-ds-base-1.3.1' - ldap/servers
by Richard Allen Megginson
ldap/servers/plugins/replication/cl5_clcache.c | 48 +++++++++++++++++++++----
1 file changed, 42 insertions(+), 6 deletions(-)
New commits:
commit fc70e4ac6accaa14d140e333829e98897f6ff164
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Wed Nov 6 14:22:31 2013 -0700
Ticket #47585 Replication Failures related to skipped entries due to cleaned rids
https://fedorahosted.org/389/ticket/47585
Reviewed by: nhosoi (Thanks!)
Branch: 389-ds-base-1.3.1
Fix Description: If a change was found in the changelog buffer that is
skipped due to having an unknown replica ID (rid), the entire buffer was
marked as CLC_STATE_NEW_RID. When the buffer is exhausted and the iterator
code goes to read in the new buffer, it would not read in the new buffer
because it only loads a new buffer if the current buffer state is
CLC_STATE_READY. I don't know why the entire buffer would be marked as
CLC_STATE_NEW_RID and stop iteration. It seems to me that just the update
should be skipped, but new buffers should be loaded in order to keep sending
non-skipped updates to the consumer.
It is possible for a CSN with an unknown RID to get into the changelog if
the server with that RID had been removed by cleanruv/cleanallruv. In that
case, the CSN should be skipped. It is assumed that the change was already
sent - cleanallruv is supposed to wait until all known changes have been
seen before removing the RID from the RUV - so it is safe to skip it.
Added additional debugging, so that we can better tell why changelog entries
were skipped.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
(cherry picked from commit cf08f1274404e4796966011a98a6a0acbbfd6070)
(cherry picked from commit 30bb98fb693ea1aac9774bdc43b923eacd72570a)
diff --git a/ldap/servers/plugins/replication/cl5_clcache.c b/ldap/servers/plugins/replication/cl5_clcache.c
index 7a6a446..8218312 100644
--- a/ldap/servers/plugins/replication/cl5_clcache.c
+++ b/ldap/servers/plugins/replication/cl5_clcache.c
@@ -120,6 +120,11 @@ struct clc_buffer {
int buf_load_cnt; /* number of loads for session */
int buf_record_cnt; /* number of changes for session */
int buf_record_skipped; /* number of changes skipped */
+ int buf_skipped_new_rid; /* number of changes skipped due to new_rid */
+ int buf_skipped_csn_gt_cons_maxcsn; /* number of changes skipped due to csn greater than consumer maxcsn */
+ int buf_skipped_up_to_date; /* number of changes skipped due to consumer being up-to-date for the given rid */
+ int buf_skipped_csn_gt_ruv; /* number of changes skipped due to preceedents are not covered by local RUV snapshot */
+ int buf_skipped_csn_covered; /* number of changes skipped due to CSNs already covered by consumer RUV */
/*
* fields that should be accessed via bl_lock or pl_lock
@@ -252,6 +257,11 @@ clcache_get_buffer ( CLC_Buffer **buf, DB *db, ReplicaId consumer_rid, const RUV
(*buf)->buf_record_skipped = 0;
(*buf)->buf_cursor = NULL;
(*buf)->buf_num_cscbs = 0;
+ (*buf)->buf_skipped_new_rid = 0;
+ (*buf)->buf_skipped_csn_gt_cons_maxcsn = 0;
+ (*buf)->buf_skipped_up_to_date = 0;
+ (*buf)->buf_skipped_csn_gt_ruv = 0;
+ (*buf)->buf_skipped_csn_covered = 0;
}
else {
*buf = clcache_new_buffer ( consumer_rid );
@@ -287,11 +297,16 @@ clcache_return_buffer ( CLC_Buffer **buf )
int i;
slapi_log_error ( SLAPI_LOG_REPL, (*buf)->buf_agmt_name,
- "session end: state=%d load=%d sent=%d skipped=%d\n",
- (*buf)->buf_state,
- (*buf)->buf_load_cnt,
- (*buf)->buf_record_cnt - (*buf)->buf_record_skipped,
- (*buf)->buf_record_skipped );
+ "session end: state=%d load=%d sent=%d skipped=%d skipped_new_rid=%d "
+ "skipped_csn_gt_cons_maxcsn=%d skipped_up_to_date=%d "
+ "skipped_csn_gt_ruv=%d skipped_csn_covered=%d\n",
+ (*buf)->buf_state,
+ (*buf)->buf_load_cnt,
+ (*buf)->buf_record_cnt - (*buf)->buf_record_skipped,
+ (*buf)->buf_record_skipped, (*buf)->buf_skipped_new_rid,
+ (*buf)->buf_skipped_csn_gt_cons_maxcsn,
+ (*buf)->buf_skipped_up_to_date, (*buf)->buf_skipped_csn_gt_ruv,
+ (*buf)->buf_skipped_csn_covered);
for ( i = 0; i < (*buf)->buf_num_cscbs; i++ ) {
clcache_free_cscb ( &(*buf)->buf_cscbs[i] );
@@ -676,6 +691,8 @@ clcache_skip_change ( CLC_Buffer *buf )
ReplicaId rid;
int skip = 1;
int i;
+ char buf_cur_csn_str[CSN_STRSIZE];
+ char oth_csn_str[CSN_STRSIZE];
do {
@@ -697,6 +714,14 @@ clcache_skip_change ( CLC_Buffer *buf )
* The consumer must have been "restored" and needs this newer update.
*/
skip = 0;
+ } else if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) {
+ csn_as_string(buf->buf_current_csn, 0, buf_cur_csn_str);
+ csn_as_string(cons_maxcsn, 0, oth_csn_str);
+ slapi_log_error(SLAPI_LOG_REPL, buf->buf_agmt_name,
+ "Skipping update because the changelog buffer current csn [%s] is "
+ "less than or equal to the consumer max csn [%s]\n",
+ buf_cur_csn_str, oth_csn_str);
+ buf->buf_skipped_csn_gt_cons_maxcsn++;
}
csn_free(&cons_maxcsn);
break;
@@ -714,7 +739,14 @@ clcache_skip_change ( CLC_Buffer *buf )
/* Skip CSN whose RID is unknown to the local RUV snapshot */
if ( i >= buf->buf_num_cscbs ) {
- buf->buf_state = CLC_STATE_NEW_RID;
+ if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) {
+ csn_as_string(buf->buf_current_csn, 0, buf_cur_csn_str);
+ slapi_log_error(SLAPI_LOG_REPL, buf->buf_agmt_name,
+ "Skipping update because the changelog buffer current csn [%s] rid "
+ "[%d] is not in the list of changelog csn buffers (length %d)\n",
+ buf_cur_csn_str, rid, buf->buf_num_cscbs);
+ }
+ buf->buf_skipped_new_rid++;
break;
}
@@ -722,17 +754,20 @@ clcache_skip_change ( CLC_Buffer *buf )
/* Skip if the consumer is already up-to-date for the RID */
if ( cscb->state == CLC_STATE_UP_TO_DATE ) {
+ buf->buf_skipped_up_to_date++;
break;
}
/* Skip CSN whose preceedents are not covered by local RUV snapshot */
if ( cscb->state == CLC_STATE_CSN_GT_RUV ) {
+ buf->buf_skipped_csn_gt_ruv++;
break;
}
/* Skip CSNs already covered by consumer RUV */
if ( cscb->consumer_maxcsn &&
csn_compare ( buf->buf_current_csn, cscb->consumer_maxcsn ) <= 0 ) {
+ buf->buf_skipped_csn_covered++;
break;
}
@@ -762,6 +797,7 @@ clcache_skip_change ( CLC_Buffer *buf )
/* Skip CSNs not covered by local RUV snapshot */
cscb->state = CLC_STATE_CSN_GT_RUV;
+ buf->buf_skipped_csn_gt_ruv++;
} while (0);
10 years, 5 months
Branch '389-ds-base-1.3.0' - ldap/servers
by Richard Allen Megginson
ldap/servers/plugins/replication/cl5_clcache.c | 48 +++++++++++++++++++++----
1 file changed, 42 insertions(+), 6 deletions(-)
New commits:
commit 7eefa121784774a2c1535404f0b95b78970b43c2
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Wed Nov 6 14:22:31 2013 -0700
Ticket #47585 Replication Failures related to skipped entries due to cleaned rids
https://fedorahosted.org/389/ticket/47585
Reviewed by: nhosoi (Thanks!)
Branch: 389-ds-base-1.3.0
Fix Description: If a change was found in the changelog buffer that is
skipped due to having an unknown replica ID (rid), the entire buffer was
marked as CLC_STATE_NEW_RID. When the buffer is exhausted and the iterator
code goes to read in the new buffer, it would not read in the new buffer
because it only loads a new buffer if the current buffer state is
CLC_STATE_READY. I don't know why the entire buffer would be marked as
CLC_STATE_NEW_RID and stop iteration. It seems to me that just the update
should be skipped, but new buffers should be loaded in order to keep sending
non-skipped updates to the consumer.
It is possible for a CSN with an unknown RID to get into the changelog if
the server with that RID had been removed by cleanruv/cleanallruv. In that
case, the CSN should be skipped. It is assumed that the change was already
sent - cleanallruv is supposed to wait until all known changes have been
seen before removing the RID from the RUV - so it is safe to skip it.
Added additional debugging, so that we can better tell why changelog entries
were skipped.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
(cherry picked from commit cf08f1274404e4796966011a98a6a0acbbfd6070)
(cherry picked from commit 30bb98fb693ea1aac9774bdc43b923eacd72570a)
(cherry picked from commit fc70e4ac6accaa14d140e333829e98897f6ff164)
diff --git a/ldap/servers/plugins/replication/cl5_clcache.c b/ldap/servers/plugins/replication/cl5_clcache.c
index 7a6a446..8218312 100644
--- a/ldap/servers/plugins/replication/cl5_clcache.c
+++ b/ldap/servers/plugins/replication/cl5_clcache.c
@@ -120,6 +120,11 @@ struct clc_buffer {
int buf_load_cnt; /* number of loads for session */
int buf_record_cnt; /* number of changes for session */
int buf_record_skipped; /* number of changes skipped */
+ int buf_skipped_new_rid; /* number of changes skipped due to new_rid */
+ int buf_skipped_csn_gt_cons_maxcsn; /* number of changes skipped due to csn greater than consumer maxcsn */
+ int buf_skipped_up_to_date; /* number of changes skipped due to consumer being up-to-date for the given rid */
+ int buf_skipped_csn_gt_ruv; /* number of changes skipped due to preceedents are not covered by local RUV snapshot */
+ int buf_skipped_csn_covered; /* number of changes skipped due to CSNs already covered by consumer RUV */
/*
* fields that should be accessed via bl_lock or pl_lock
@@ -252,6 +257,11 @@ clcache_get_buffer ( CLC_Buffer **buf, DB *db, ReplicaId consumer_rid, const RUV
(*buf)->buf_record_skipped = 0;
(*buf)->buf_cursor = NULL;
(*buf)->buf_num_cscbs = 0;
+ (*buf)->buf_skipped_new_rid = 0;
+ (*buf)->buf_skipped_csn_gt_cons_maxcsn = 0;
+ (*buf)->buf_skipped_up_to_date = 0;
+ (*buf)->buf_skipped_csn_gt_ruv = 0;
+ (*buf)->buf_skipped_csn_covered = 0;
}
else {
*buf = clcache_new_buffer ( consumer_rid );
@@ -287,11 +297,16 @@ clcache_return_buffer ( CLC_Buffer **buf )
int i;
slapi_log_error ( SLAPI_LOG_REPL, (*buf)->buf_agmt_name,
- "session end: state=%d load=%d sent=%d skipped=%d\n",
- (*buf)->buf_state,
- (*buf)->buf_load_cnt,
- (*buf)->buf_record_cnt - (*buf)->buf_record_skipped,
- (*buf)->buf_record_skipped );
+ "session end: state=%d load=%d sent=%d skipped=%d skipped_new_rid=%d "
+ "skipped_csn_gt_cons_maxcsn=%d skipped_up_to_date=%d "
+ "skipped_csn_gt_ruv=%d skipped_csn_covered=%d\n",
+ (*buf)->buf_state,
+ (*buf)->buf_load_cnt,
+ (*buf)->buf_record_cnt - (*buf)->buf_record_skipped,
+ (*buf)->buf_record_skipped, (*buf)->buf_skipped_new_rid,
+ (*buf)->buf_skipped_csn_gt_cons_maxcsn,
+ (*buf)->buf_skipped_up_to_date, (*buf)->buf_skipped_csn_gt_ruv,
+ (*buf)->buf_skipped_csn_covered);
for ( i = 0; i < (*buf)->buf_num_cscbs; i++ ) {
clcache_free_cscb ( &(*buf)->buf_cscbs[i] );
@@ -676,6 +691,8 @@ clcache_skip_change ( CLC_Buffer *buf )
ReplicaId rid;
int skip = 1;
int i;
+ char buf_cur_csn_str[CSN_STRSIZE];
+ char oth_csn_str[CSN_STRSIZE];
do {
@@ -697,6 +714,14 @@ clcache_skip_change ( CLC_Buffer *buf )
* The consumer must have been "restored" and needs this newer update.
*/
skip = 0;
+ } else if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) {
+ csn_as_string(buf->buf_current_csn, 0, buf_cur_csn_str);
+ csn_as_string(cons_maxcsn, 0, oth_csn_str);
+ slapi_log_error(SLAPI_LOG_REPL, buf->buf_agmt_name,
+ "Skipping update because the changelog buffer current csn [%s] is "
+ "less than or equal to the consumer max csn [%s]\n",
+ buf_cur_csn_str, oth_csn_str);
+ buf->buf_skipped_csn_gt_cons_maxcsn++;
}
csn_free(&cons_maxcsn);
break;
@@ -714,7 +739,14 @@ clcache_skip_change ( CLC_Buffer *buf )
/* Skip CSN whose RID is unknown to the local RUV snapshot */
if ( i >= buf->buf_num_cscbs ) {
- buf->buf_state = CLC_STATE_NEW_RID;
+ if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) {
+ csn_as_string(buf->buf_current_csn, 0, buf_cur_csn_str);
+ slapi_log_error(SLAPI_LOG_REPL, buf->buf_agmt_name,
+ "Skipping update because the changelog buffer current csn [%s] rid "
+ "[%d] is not in the list of changelog csn buffers (length %d)\n",
+ buf_cur_csn_str, rid, buf->buf_num_cscbs);
+ }
+ buf->buf_skipped_new_rid++;
break;
}
@@ -722,17 +754,20 @@ clcache_skip_change ( CLC_Buffer *buf )
/* Skip if the consumer is already up-to-date for the RID */
if ( cscb->state == CLC_STATE_UP_TO_DATE ) {
+ buf->buf_skipped_up_to_date++;
break;
}
/* Skip CSN whose preceedents are not covered by local RUV snapshot */
if ( cscb->state == CLC_STATE_CSN_GT_RUV ) {
+ buf->buf_skipped_csn_gt_ruv++;
break;
}
/* Skip CSNs already covered by consumer RUV */
if ( cscb->consumer_maxcsn &&
csn_compare ( buf->buf_current_csn, cscb->consumer_maxcsn ) <= 0 ) {
+ buf->buf_skipped_csn_covered++;
break;
}
@@ -762,6 +797,7 @@ clcache_skip_change ( CLC_Buffer *buf )
/* Skip CSNs not covered by local RUV snapshot */
cscb->state = CLC_STATE_CSN_GT_RUV;
+ buf->buf_skipped_csn_gt_ruv++;
} while (0);
10 years, 5 months
Branch '389-ds-base-1.2.11' - ldap/servers
by Richard Allen Megginson
ldap/servers/plugins/replication/cl5_clcache.c | 48 +++++++++++++++++++++----
1 file changed, 42 insertions(+), 6 deletions(-)
New commits:
commit c783d159a3baa005f0a5f007d886961e2128bdcc
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Wed Nov 6 14:22:31 2013 -0700
Ticket #47585 Replication Failures related to skipped entries due to cleaned rids
https://fedorahosted.org/389/ticket/47585
Reviewed by: nhosoi (Thanks!)
Branch: 389-ds-base-1.2.11
Fix Description: If a change was found in the changelog buffer that is
skipped due to having an unknown replica ID (rid), the entire buffer was
marked as CLC_STATE_NEW_RID. When the buffer is exhausted and the iterator
code goes to read in the new buffer, it would not read in the new buffer
because it only loads a new buffer if the current buffer state is
CLC_STATE_READY. I don't know why the entire buffer would be marked as
CLC_STATE_NEW_RID and stop iteration. It seems to me that just the update
should be skipped, but new buffers should be loaded in order to keep sending
non-skipped updates to the consumer.
It is possible for a CSN with an unknown RID to get into the changelog if
the server with that RID had been removed by cleanruv/cleanallruv. In that
case, the CSN should be skipped. It is assumed that the change was already
sent - cleanallruv is supposed to wait until all known changes have been
seen before removing the RID from the RUV - so it is safe to skip it.
Added additional debugging, so that we can better tell why changelog entries
were skipped.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
(cherry picked from commit cf08f1274404e4796966011a98a6a0acbbfd6070)
(cherry picked from commit 30bb98fb693ea1aac9774bdc43b923eacd72570a)
(cherry picked from commit fc70e4ac6accaa14d140e333829e98897f6ff164)
(cherry picked from commit 7eefa121784774a2c1535404f0b95b78970b43c2)
diff --git a/ldap/servers/plugins/replication/cl5_clcache.c b/ldap/servers/plugins/replication/cl5_clcache.c
index 7a6a446..8218312 100644
--- a/ldap/servers/plugins/replication/cl5_clcache.c
+++ b/ldap/servers/plugins/replication/cl5_clcache.c
@@ -120,6 +120,11 @@ struct clc_buffer {
int buf_load_cnt; /* number of loads for session */
int buf_record_cnt; /* number of changes for session */
int buf_record_skipped; /* number of changes skipped */
+ int buf_skipped_new_rid; /* number of changes skipped due to new_rid */
+ int buf_skipped_csn_gt_cons_maxcsn; /* number of changes skipped due to csn greater than consumer maxcsn */
+ int buf_skipped_up_to_date; /* number of changes skipped due to consumer being up-to-date for the given rid */
+ int buf_skipped_csn_gt_ruv; /* number of changes skipped due to preceedents are not covered by local RUV snapshot */
+ int buf_skipped_csn_covered; /* number of changes skipped due to CSNs already covered by consumer RUV */
/*
* fields that should be accessed via bl_lock or pl_lock
@@ -252,6 +257,11 @@ clcache_get_buffer ( CLC_Buffer **buf, DB *db, ReplicaId consumer_rid, const RUV
(*buf)->buf_record_skipped = 0;
(*buf)->buf_cursor = NULL;
(*buf)->buf_num_cscbs = 0;
+ (*buf)->buf_skipped_new_rid = 0;
+ (*buf)->buf_skipped_csn_gt_cons_maxcsn = 0;
+ (*buf)->buf_skipped_up_to_date = 0;
+ (*buf)->buf_skipped_csn_gt_ruv = 0;
+ (*buf)->buf_skipped_csn_covered = 0;
}
else {
*buf = clcache_new_buffer ( consumer_rid );
@@ -287,11 +297,16 @@ clcache_return_buffer ( CLC_Buffer **buf )
int i;
slapi_log_error ( SLAPI_LOG_REPL, (*buf)->buf_agmt_name,
- "session end: state=%d load=%d sent=%d skipped=%d\n",
- (*buf)->buf_state,
- (*buf)->buf_load_cnt,
- (*buf)->buf_record_cnt - (*buf)->buf_record_skipped,
- (*buf)->buf_record_skipped );
+ "session end: state=%d load=%d sent=%d skipped=%d skipped_new_rid=%d "
+ "skipped_csn_gt_cons_maxcsn=%d skipped_up_to_date=%d "
+ "skipped_csn_gt_ruv=%d skipped_csn_covered=%d\n",
+ (*buf)->buf_state,
+ (*buf)->buf_load_cnt,
+ (*buf)->buf_record_cnt - (*buf)->buf_record_skipped,
+ (*buf)->buf_record_skipped, (*buf)->buf_skipped_new_rid,
+ (*buf)->buf_skipped_csn_gt_cons_maxcsn,
+ (*buf)->buf_skipped_up_to_date, (*buf)->buf_skipped_csn_gt_ruv,
+ (*buf)->buf_skipped_csn_covered);
for ( i = 0; i < (*buf)->buf_num_cscbs; i++ ) {
clcache_free_cscb ( &(*buf)->buf_cscbs[i] );
@@ -676,6 +691,8 @@ clcache_skip_change ( CLC_Buffer *buf )
ReplicaId rid;
int skip = 1;
int i;
+ char buf_cur_csn_str[CSN_STRSIZE];
+ char oth_csn_str[CSN_STRSIZE];
do {
@@ -697,6 +714,14 @@ clcache_skip_change ( CLC_Buffer *buf )
* The consumer must have been "restored" and needs this newer update.
*/
skip = 0;
+ } else if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) {
+ csn_as_string(buf->buf_current_csn, 0, buf_cur_csn_str);
+ csn_as_string(cons_maxcsn, 0, oth_csn_str);
+ slapi_log_error(SLAPI_LOG_REPL, buf->buf_agmt_name,
+ "Skipping update because the changelog buffer current csn [%s] is "
+ "less than or equal to the consumer max csn [%s]\n",
+ buf_cur_csn_str, oth_csn_str);
+ buf->buf_skipped_csn_gt_cons_maxcsn++;
}
csn_free(&cons_maxcsn);
break;
@@ -714,7 +739,14 @@ clcache_skip_change ( CLC_Buffer *buf )
/* Skip CSN whose RID is unknown to the local RUV snapshot */
if ( i >= buf->buf_num_cscbs ) {
- buf->buf_state = CLC_STATE_NEW_RID;
+ if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) {
+ csn_as_string(buf->buf_current_csn, 0, buf_cur_csn_str);
+ slapi_log_error(SLAPI_LOG_REPL, buf->buf_agmt_name,
+ "Skipping update because the changelog buffer current csn [%s] rid "
+ "[%d] is not in the list of changelog csn buffers (length %d)\n",
+ buf_cur_csn_str, rid, buf->buf_num_cscbs);
+ }
+ buf->buf_skipped_new_rid++;
break;
}
@@ -722,17 +754,20 @@ clcache_skip_change ( CLC_Buffer *buf )
/* Skip if the consumer is already up-to-date for the RID */
if ( cscb->state == CLC_STATE_UP_TO_DATE ) {
+ buf->buf_skipped_up_to_date++;
break;
}
/* Skip CSN whose preceedents are not covered by local RUV snapshot */
if ( cscb->state == CLC_STATE_CSN_GT_RUV ) {
+ buf->buf_skipped_csn_gt_ruv++;
break;
}
/* Skip CSNs already covered by consumer RUV */
if ( cscb->consumer_maxcsn &&
csn_compare ( buf->buf_current_csn, cscb->consumer_maxcsn ) <= 0 ) {
+ buf->buf_skipped_csn_covered++;
break;
}
@@ -762,6 +797,7 @@ clcache_skip_change ( CLC_Buffer *buf )
/* Skip CSNs not covered by local RUV snapshot */
cscb->state = CLC_STATE_CSN_GT_RUV;
+ buf->buf_skipped_csn_gt_ruv++;
} while (0);
10 years, 5 months