Branch '389-ds-base-1.3.2' - ldap/servers
by Noriko Hosoi
ldap/servers/plugins/replication/windows_protocol_util.c | 122 ++++++++++++++-
1 file changed, 117 insertions(+), 5 deletions(-)
New commits:
commit 86515d1b18a96b9d7e6143f870b343030a7af5a7
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Tue Feb 18 10:36:15 2014 -0800
Ticket #47642 - Windows Sync group issues
Bug Description: When an entry is moved on AD, and the entry is
a member of a group, the value of the member in the group is
automatically updated. But Windows Sync Control request only
returns the renamed entry; it does not return the group having
the member in it even though the value is updated. This is
because an AD group stores DNT (Distinguish Name Tag -- ID in
integer) instead of the dn itself. Since the rename operation
does not change DNT, the group entry on AD has no change, either.
On the DS side, the group entry stores the full DN which needs
to be adjusted to the renamed DN to complete the synchronization
with AD.
Fix Description: Once rename operation is received from AD,
windows_update_local_entry searches groups having a member value
matches the pre-renamed dn on DS, and replaces the old dn with the
renamed one.
Thanks to tbordaz(a)redhat.com for pointing out the possibility of
NULL dereference. The problem is fixed, as well.
Thanks to rmeggins(a)redhat.com for suggesting to escape the search
filter value. It was added.
https://fedorahosted.org/389/ticket/47642
(cherry picked from commit 98ddd817e26f236adebd80270ec71d7ec372c20e)
diff --git a/ldap/servers/plugins/replication/windows_protocol_util.c b/ldap/servers/plugins/replication/windows_protocol_util.c
index 69ac3a3..caeb388 100644
--- a/ldap/servers/plugins/replication/windows_protocol_util.c
+++ b/ldap/servers/plugins/replication/windows_protocol_util.c
@@ -4264,6 +4264,7 @@ map_entry_dn_inbound_ext(Slapi_Entry *e, Slapi_DN **dn, const Repl_Agmt *ra, int
} else
{
/* Error, no username */
+ retval = ENTRY_NOTFOUND;
}
}
if (new_dn)
@@ -5214,7 +5215,7 @@ windows_update_remote_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry
static int
windows_update_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,Slapi_Entry *local_entry)
{
- Slapi_Mods smods = {0};
+ Slapi_Mods smods;
int retval = 0;
Slapi_PBlock *pb = NULL;
int do_modify = 0;
@@ -5226,14 +5227,24 @@ windows_update_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,
Slapi_DN *mapped_sdn = NULL;
Slapi_RDN rdn = {0};
Slapi_Entry *orig_local_entry = NULL;
+ const Slapi_DN *orig_local_sdn = NULL;
+ /* Variables for updating local groups */
+ Slapi_Entry **entries = NULL;
+ char *filter_string = NULL;
+ const Slapi_DN *local_subtree = NULL;
+ const Slapi_DN *local_subtree_sdn = NULL;
+ char *attrs[3];
+ /* Variables for updating local groups */
+
+ slapi_mods_init(&smods, 0);
windows_is_local_entry_user_or_group(local_entry, &is_user, &is_group);
/* Get the mapped DN. We don't want to locate the existing entry by
* guid or username. We want to get the mapped DN just as we would
* if we were creating a new entry. */
retval = map_entry_dn_inbound_ext(remote_entry, &mapped_sdn, prp->agmt, 0 /* use_guid */, 0 /* use_username */);
- if (retval != 0) {
+ if (retval || (NULL == mapped_sdn)) {
slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
"unable to map remote entry to local DN\n");
return retval;
@@ -5255,8 +5266,10 @@ windows_update_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,
&newsuperior, 0 /* to_windows */);
if (newsuperior || newrdn) {
+ char *escaped_filter_val;
+ int free_it = 0;
/* remote parent is different from the local parent */
- Slapi_PBlock *pb = slapi_pblock_new ();
+ pb = slapi_pblock_new ();
if (NULL == newrdn) {
newdn = slapi_entry_get_dn_const(local_entry);
@@ -5303,9 +5316,108 @@ windows_update_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,
orig_local_entry = NULL;
goto bail;
}
- }
- slapi_mods_init (&smods, 0);
+ /* WinSync control req does not return the member updates
+ * in the groups caused by moving member entries.
+ * We need to update the local groups manually... */
+ local_subtree = agmt_get_replarea(prp->agmt);
+ local_subtree_sdn = local_subtree;
+ orig_local_sdn = slapi_entry_get_sdn_const(orig_local_entry);
+ escaped_filter_val = slapi_escape_filter_value((char *)slapi_sdn_get_ndn(orig_local_sdn),
+ slapi_sdn_get_ndn_len(orig_local_sdn));
+ if(escaped_filter_val) {
+ free_it = 1;
+ } else {
+ escaped_filter_val = (char *)slapi_sdn_get_ndn(orig_local_sdn);
+ }
+ /* Search entries which have pre-renamed members */
+ filter_string = PR_smprintf("(&(objectclass=ntGroup)(|(member=%s)(uniquemember=%s)))",
+ escaped_filter_val, escaped_filter_val);
+ attrs[0] = "member";
+ attrs[1] = "uniquemember";
+ attrs[2] = NULL;
+ pb = slapi_pblock_new ();
+ slapi_search_internal_set_pb(pb, slapi_sdn_get_dn(local_subtree_sdn),
+ LDAP_SCOPE_SUBTREE, filter_string, attrs, 0, NULL, NULL,
+ repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0);
+ slapi_search_internal_pb(pb);
+ if (free_it) {
+ slapi_ch_free_string(&escaped_filter_val);
+ }
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &retval);
+ if (LDAP_SUCCESS == retval) {
+ Slapi_Entry **ep;
+ const char *prev_member = slapi_sdn_get_ndn(orig_local_sdn);
+ const char *new_member = slapi_sdn_get_ndn(mapped_sdn);
+ size_t prev_member_len = slapi_sdn_get_ndn_len(orig_local_sdn);
+ size_t new_member_len = strlen(new_member);
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+ for (ep = entries; ep && *ep; ep++) {
+ /* there are group entries whose member matches the renamed entry. */
+ Slapi_PBlock *mod_pb = NULL;
+ Slapi_Attr *mattr = NULL;
+ Slapi_Attr *umattr = NULL;
+ char *type = NULL;
+ slapi_entry_attr_find(*ep, "member", &mattr);
+ slapi_entry_attr_find(*ep, "uniquemember", &umattr);
+ if (mattr) {
+ if (umattr) {
+ /* This entry has both member and uniquemember ... */
+ Slapi_Value *v = NULL;
+ int i = 0;
+ for (i = slapi_attr_first_value(mattr, &v);
+ v && (i != -1);
+ i = slapi_attr_next_value(mattr, i, &v)) {
+ const char *s = slapi_value_get_string(v);
+ if (NULL == s) {
+ continue;
+ }
+ if (0 == strcasecmp(s, prev_member)) {
+ type = "member";
+ break;
+ }
+ }
+ if (!type) {
+ type = "uniquemember";
+ }
+ } else {
+ type = "member";
+ }
+ } else {
+ if (umattr) {
+ type = "uniquemember";
+ }
+ }
+ if (type) {
+ mod_pb = slapi_pblock_new();
+ slapi_mods_add(&smods, LDAP_MOD_DELETE, type, prev_member_len, prev_member);
+ slapi_mods_add(&smods, LDAP_MOD_ADD, type, new_member_len, new_member);
+ slapi_modify_internal_set_pb_ext(mod_pb, slapi_entry_get_sdn(*ep),
+ slapi_mods_get_ldapmods_byref(&smods), NULL, NULL,
+ repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION),
+ 0);
+ slapi_modify_internal_pb(mod_pb);
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &retval);
+ if (retval) {
+ slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
+ "windows_update_local_entry: "
+ "failed to modify entry %s replacing %s with %s "
+ "- error %d:%s\n",
+ slapi_entry_get_dn(*ep), prev_member, new_member,
+ retval, ldap_err2string(retval));
+ }
+ slapi_pblock_destroy(mod_pb);
+ slapi_mods_done(&smods);
+ } /* if (type) */
+ } /* for (ep = entries; ep && *ep; ep++) */
+ } /* if (LDAP_SUCCESS == retval) - searching with "(|(member=..)(uniquemember=..)) */
+ slapi_free_search_results_internal(pb);
+ slapi_pblock_destroy(pb);
+ if (filter_string) {
+ PR_smprintf_free(filter_string);
+ }
+ slapi_sdn_free((Slapi_DN **)&local_subtree);
+ } /* if (newsuperior || newrdn) */
retval = windows_generate_update_mods(prp,remote_entry,local_entry,0,&smods,&do_modify);
/* Now perform the modify if we need to */
10 years, 2 months
ldap/servers
by Noriko Hosoi
ldap/servers/plugins/replication/windows_protocol_util.c | 122 ++++++++++++++-
1 file changed, 117 insertions(+), 5 deletions(-)
New commits:
commit 98ddd817e26f236adebd80270ec71d7ec372c20e
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Tue Feb 18 10:36:15 2014 -0800
Ticket #47642 - Windows Sync group issues
Bug Description: When an entry is moved on AD, and the entry is
a member of a group, the value of the member in the group is
automatically updated. But Windows Sync Control request only
returns the renamed entry; it does not return the group having
the member in it even though the value is updated. This is
because an AD group stores DNT (Distinguish Name Tag -- ID in
integer) instead of the dn itself. Since the rename operation
does not change DNT, the group entry on AD has no change, either.
On the DS side, the group entry stores the full DN which needs
to be adjusted to the renamed DN to complete the synchronization
with AD.
Fix Description: Once rename operation is received from AD,
windows_update_local_entry searches groups having a member value
matches the pre-renamed dn on DS, and replaces the old dn with the
renamed one.
Thanks to tbordaz(a)redhat.com for pointing out the possibility of
NULL dereference. The problem is fixed, as well.
Thanks to rmeggins(a)redhat.com for suggesting to escape the search
filter value. It was added.
https://fedorahosted.org/389/ticket/47642
diff --git a/ldap/servers/plugins/replication/windows_protocol_util.c b/ldap/servers/plugins/replication/windows_protocol_util.c
index 69ac3a3..caeb388 100644
--- a/ldap/servers/plugins/replication/windows_protocol_util.c
+++ b/ldap/servers/plugins/replication/windows_protocol_util.c
@@ -4264,6 +4264,7 @@ map_entry_dn_inbound_ext(Slapi_Entry *e, Slapi_DN **dn, const Repl_Agmt *ra, int
} else
{
/* Error, no username */
+ retval = ENTRY_NOTFOUND;
}
}
if (new_dn)
@@ -5214,7 +5215,7 @@ windows_update_remote_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry
static int
windows_update_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,Slapi_Entry *local_entry)
{
- Slapi_Mods smods = {0};
+ Slapi_Mods smods;
int retval = 0;
Slapi_PBlock *pb = NULL;
int do_modify = 0;
@@ -5226,14 +5227,24 @@ windows_update_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,
Slapi_DN *mapped_sdn = NULL;
Slapi_RDN rdn = {0};
Slapi_Entry *orig_local_entry = NULL;
+ const Slapi_DN *orig_local_sdn = NULL;
+ /* Variables for updating local groups */
+ Slapi_Entry **entries = NULL;
+ char *filter_string = NULL;
+ const Slapi_DN *local_subtree = NULL;
+ const Slapi_DN *local_subtree_sdn = NULL;
+ char *attrs[3];
+ /* Variables for updating local groups */
+
+ slapi_mods_init(&smods, 0);
windows_is_local_entry_user_or_group(local_entry, &is_user, &is_group);
/* Get the mapped DN. We don't want to locate the existing entry by
* guid or username. We want to get the mapped DN just as we would
* if we were creating a new entry. */
retval = map_entry_dn_inbound_ext(remote_entry, &mapped_sdn, prp->agmt, 0 /* use_guid */, 0 /* use_username */);
- if (retval != 0) {
+ if (retval || (NULL == mapped_sdn)) {
slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
"unable to map remote entry to local DN\n");
return retval;
@@ -5255,8 +5266,10 @@ windows_update_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,
&newsuperior, 0 /* to_windows */);
if (newsuperior || newrdn) {
+ char *escaped_filter_val;
+ int free_it = 0;
/* remote parent is different from the local parent */
- Slapi_PBlock *pb = slapi_pblock_new ();
+ pb = slapi_pblock_new ();
if (NULL == newrdn) {
newdn = slapi_entry_get_dn_const(local_entry);
@@ -5303,9 +5316,108 @@ windows_update_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,
orig_local_entry = NULL;
goto bail;
}
- }
- slapi_mods_init (&smods, 0);
+ /* WinSync control req does not return the member updates
+ * in the groups caused by moving member entries.
+ * We need to update the local groups manually... */
+ local_subtree = agmt_get_replarea(prp->agmt);
+ local_subtree_sdn = local_subtree;
+ orig_local_sdn = slapi_entry_get_sdn_const(orig_local_entry);
+ escaped_filter_val = slapi_escape_filter_value((char *)slapi_sdn_get_ndn(orig_local_sdn),
+ slapi_sdn_get_ndn_len(orig_local_sdn));
+ if(escaped_filter_val) {
+ free_it = 1;
+ } else {
+ escaped_filter_val = (char *)slapi_sdn_get_ndn(orig_local_sdn);
+ }
+ /* Search entries which have pre-renamed members */
+ filter_string = PR_smprintf("(&(objectclass=ntGroup)(|(member=%s)(uniquemember=%s)))",
+ escaped_filter_val, escaped_filter_val);
+ attrs[0] = "member";
+ attrs[1] = "uniquemember";
+ attrs[2] = NULL;
+ pb = slapi_pblock_new ();
+ slapi_search_internal_set_pb(pb, slapi_sdn_get_dn(local_subtree_sdn),
+ LDAP_SCOPE_SUBTREE, filter_string, attrs, 0, NULL, NULL,
+ repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0);
+ slapi_search_internal_pb(pb);
+ if (free_it) {
+ slapi_ch_free_string(&escaped_filter_val);
+ }
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &retval);
+ if (LDAP_SUCCESS == retval) {
+ Slapi_Entry **ep;
+ const char *prev_member = slapi_sdn_get_ndn(orig_local_sdn);
+ const char *new_member = slapi_sdn_get_ndn(mapped_sdn);
+ size_t prev_member_len = slapi_sdn_get_ndn_len(orig_local_sdn);
+ size_t new_member_len = strlen(new_member);
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+ for (ep = entries; ep && *ep; ep++) {
+ /* there are group entries whose member matches the renamed entry. */
+ Slapi_PBlock *mod_pb = NULL;
+ Slapi_Attr *mattr = NULL;
+ Slapi_Attr *umattr = NULL;
+ char *type = NULL;
+ slapi_entry_attr_find(*ep, "member", &mattr);
+ slapi_entry_attr_find(*ep, "uniquemember", &umattr);
+ if (mattr) {
+ if (umattr) {
+ /* This entry has both member and uniquemember ... */
+ Slapi_Value *v = NULL;
+ int i = 0;
+ for (i = slapi_attr_first_value(mattr, &v);
+ v && (i != -1);
+ i = slapi_attr_next_value(mattr, i, &v)) {
+ const char *s = slapi_value_get_string(v);
+ if (NULL == s) {
+ continue;
+ }
+ if (0 == strcasecmp(s, prev_member)) {
+ type = "member";
+ break;
+ }
+ }
+ if (!type) {
+ type = "uniquemember";
+ }
+ } else {
+ type = "member";
+ }
+ } else {
+ if (umattr) {
+ type = "uniquemember";
+ }
+ }
+ if (type) {
+ mod_pb = slapi_pblock_new();
+ slapi_mods_add(&smods, LDAP_MOD_DELETE, type, prev_member_len, prev_member);
+ slapi_mods_add(&smods, LDAP_MOD_ADD, type, new_member_len, new_member);
+ slapi_modify_internal_set_pb_ext(mod_pb, slapi_entry_get_sdn(*ep),
+ slapi_mods_get_ldapmods_byref(&smods), NULL, NULL,
+ repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION),
+ 0);
+ slapi_modify_internal_pb(mod_pb);
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &retval);
+ if (retval) {
+ slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
+ "windows_update_local_entry: "
+ "failed to modify entry %s replacing %s with %s "
+ "- error %d:%s\n",
+ slapi_entry_get_dn(*ep), prev_member, new_member,
+ retval, ldap_err2string(retval));
+ }
+ slapi_pblock_destroy(mod_pb);
+ slapi_mods_done(&smods);
+ } /* if (type) */
+ } /* for (ep = entries; ep && *ep; ep++) */
+ } /* if (LDAP_SUCCESS == retval) - searching with "(|(member=..)(uniquemember=..)) */
+ slapi_free_search_results_internal(pb);
+ slapi_pblock_destroy(pb);
+ if (filter_string) {
+ PR_smprintf_free(filter_string);
+ }
+ slapi_sdn_free((Slapi_DN **)&local_subtree);
+ } /* if (newsuperior || newrdn) */
retval = windows_generate_update_mods(prp,remote_entry,local_entry,0,&smods,&do_modify);
/* Now perform the modify if we need to */
10 years, 2 months
Branch '389-ds-base-1.3.1' - ldap/servers
by Ludwig Krispenz
ldap/servers/plugins/acl/acl_ext.c | 6 ++++++
1 file changed, 6 insertions(+)
New commits:
commit 377266ebb2ff488aa3cc4b96990c002db7e6103e
Author: Ludwig Krispenz <lkrispen(a)redhat.com>
Date: Tue Feb 18 11:40:16 2014 +0100
Ticket 47704 - invalid sizelimits in aci group evaluation
Bug Description: aci group evaluation fails because of sizelimit exceeded
but it is exceeded because it is -1476887876 or another
negative integer becasue operation parameter are a union
based on operation types and so for otehr than search
the value is dependent on the operation params
Fix Description: treat any negative integer like -1 (unlimited). A better fix
would be to introduce a specific configuration param or
to abondon the limit in group evaluation at all. But this
could introduce backward compatibility problems and
will be handled in ticket 47703 for newer versions
https://fedorahosted.org/389/ticket/47704
Reviewed by: Rich, thanks
diff --git a/ldap/servers/plugins/acl/acl_ext.c b/ldap/servers/plugins/acl/acl_ext.c
index ee2dd0f..b9cec43 100644
--- a/ldap/servers/plugins/acl/acl_ext.c
+++ b/ldap/servers/plugins/acl/acl_ext.c
@@ -836,6 +836,12 @@ acl_init_aclpb ( Slapi_PBlock *pb , Acl_PBlock *aclpb, const char *ndn, int copy
slapi_pblock_get( pb, SLAPI_SEARCH_SIZELIMIT, &aclpb->aclpb_max_member_sizelimit );
if ( aclpb->aclpb_max_member_sizelimit == 0 ) {
aclpb->aclpb_max_member_sizelimit = SLAPD_DEFAULT_LOOKTHROUGHLIMIT;
+ } else if ( aclpb->aclpb_max_member_sizelimit < -1 ) {
+ /* handle the case of a negtive size limit either set or due
+ * to bug bz1065971. The member size limit should be dropped,
+ * but for backward compatibility to the best we can
+ */
+ aclpb->aclpb_max_member_sizelimit = -1;
}
slapi_pblock_get( pb, SLAPI_OPERATION_TYPE, &aclpb->aclpb_optype );
10 years, 2 months
ldap/servers
by Ludwig Krispenz
ldap/servers/plugins/acl/acl_ext.c | 6 ++++++
1 file changed, 6 insertions(+)
New commits:
commit e5b83f596a2cfd813d9d4c6cb38435d338cf19e6
Author: Ludwig Krispenz <lkrispen(a)redhat.com>
Date: Tue Feb 18 11:40:16 2014 +0100
Ticket 47704 - invalid sizelimits in aci group evaluation
Bug Description: aci group evaluation fails because of sizelimit exceeded
but it is exceeded because it is -1476887876 or another
negative integer becasue operation parameter are a union
based on operation types and so for otehr than search
the value is dependent on the operation params
Fix Description: treat any negative integer like -1 (unlimited). A better fix
would be to introduce a specific configuration param or
to abondon the limit in group evaluation at all. But this
could introduce backward compatibility problems and
will be handled in ticket 47703 for newer versions
https://fedorahosted.org/389/ticket/47704
Reviewed by: Rich, thanks
diff --git a/ldap/servers/plugins/acl/acl_ext.c b/ldap/servers/plugins/acl/acl_ext.c
index a1ff073..91135b7 100644
--- a/ldap/servers/plugins/acl/acl_ext.c
+++ b/ldap/servers/plugins/acl/acl_ext.c
@@ -881,6 +881,12 @@ acl_init_aclpb ( Slapi_PBlock *pb, Acl_PBlock *aclpb, const char *ndn, int copy_
slapi_pblock_get( pb, SLAPI_SEARCH_SIZELIMIT, &aclpb->aclpb_max_member_sizelimit );
if ( aclpb->aclpb_max_member_sizelimit == 0 ) {
aclpb->aclpb_max_member_sizelimit = SLAPD_DEFAULT_LOOKTHROUGHLIMIT;
+ } else if ( aclpb->aclpb_max_member_sizelimit < -1 ) {
+ /* handle the case of a negtive size limit either set or due
+ * to bug bz1065971. The member size limit should be dropped,
+ * but for backward compatibility to the best we can
+ */
+ aclpb->aclpb_max_member_sizelimit = -1;
}
slapi_pblock_get( pb, SLAPI_OPERATION_TYPE, &aclpb->aclpb_optype );
10 years, 2 months
ldap/servers
by Noriko Hosoi
ldap/servers/slapd/back-ldbm/seq.c | 58 +++++++++++++++++++++++++------------
1 file changed, 40 insertions(+), 18 deletions(-)
New commits:
commit a037d1cc353bd5f5b0ed11595a66fddc62592a42
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Mon Feb 17 11:35:49 2014 -0800
Ticket #47602 - Make ldbm_back_seq independently support transactions
Description: If ldbm_back_seq is called as a child of transaction, it
fails to access the on-going transaction data. This patch picks up
the parent transaction if any, and it calls dblayer_read_txn_begin with
the parent transaction. If the read transaction is aborted by DEADLOCK,
it retries.
https://fedorahosted.org/389/ticket/47602
Reviewed by mreynolds(a)redhat.com (Thank you, Mark!!)
diff --git a/ldap/servers/slapd/back-ldbm/seq.c b/ldap/servers/slapd/back-ldbm/seq.c
index 10484fd..a75879c 100644
--- a/ldap/servers/slapd/back-ldbm/seq.c
+++ b/ldap/servers/slapd/back-ldbm/seq.c
@@ -73,6 +73,7 @@ ldbm_back_seq( Slapi_PBlock *pb )
struct ldbminfo *li;
IDList *idl = NULL;
back_txn txn = {NULL};
+ back_txnid parent_txn;
struct attrinfo *ai = NULL;
DB *db;
DBC *dbc = NULL;
@@ -91,13 +92,14 @@ ldbm_back_seq( Slapi_PBlock *pb )
slapi_pblock_get( pb, SLAPI_SEQ_ATTRNAME, &attrname );
slapi_pblock_get( pb, SLAPI_SEQ_VAL, &val );
slapi_pblock_get( pb, SLAPI_REQUESTOR_ISROOT, &isroot );
- slapi_pblock_get( pb, SLAPI_TXN, &txn.back_txn_txn );
+ slapi_pblock_get( pb, SLAPI_TXN, (void **)&parent_txn );
inst = (ldbm_instance *) be->be_instance_info;
- if ( !txn.back_txn_txn ) {
- dblayer_txn_init( li, &txn );
- slapi_pblock_set( pb, SLAPI_TXN, txn.back_txn_txn );
+ dblayer_txn_init( li, &txn );
+ if (!parent_txn) {
+ parent_txn = txn.back_txn_txn;
+ slapi_pblock_set( pb, SLAPI_TXN, parent_txn );
}
/* Validate arguments */
@@ -133,9 +135,11 @@ ldbm_back_seq( Slapi_PBlock *pb )
slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
return -1;
}
-
+retry:
+ if (txn.back_txn_txn) {
+ dblayer_read_txn_begin(be, parent_txn, &txn);
+ }
/* First, get a database cursor */
-
return_value = db->cursor(db, txn.back_txn_txn, &dbc, 0);
if (0 == return_value)
@@ -221,8 +225,7 @@ ldbm_back_seq( Slapi_PBlock *pb )
key.data = &keystring;
key.size = 1;
return_value = dbc->c_get(dbc,&key,&data,DB_SET_RANGE);
- if (0 == return_value || DB_NOTFOUND == return_value)
- {
+ if ((0 == return_value) || (DB_NOTFOUND == return_value)) {
slapi_ch_free(&(data.data));
return_value = dbc->c_get(dbc,&key,&data,DB_PREV);
}
@@ -232,29 +235,48 @@ ldbm_back_seq( Slapi_PBlock *pb )
dbc->c_close(dbc);
- if (0 == return_value && key.data!=NULL)
- {
-
+ if ((0 == return_value) || (DB_NOTFOUND == return_value)) {
+ if (txn.back_txn_txn) {
+ dblayer_read_txn_commit(be, &txn);
+ }
/* Now check that the key we eventually settled on was an equality key ! */
- if (*((char*)key.data) == EQ_PREFIX)
- {
+ if (key.data && *((char*)key.data) == EQ_PREFIX) {
/* Retrieve the idlist for this key */
key.flags = 0;
for (retry_count = 0; retry_count < IDL_FETCH_RETRY_COUNT; retry_count++) {
err = NEW_IDL_DEFAULT;
idl_free(idl);
- idl = idl_fetch( be, db, &key, txn.back_txn_txn, ai, &err );
+ idl = idl_fetch( be, db, &key, parent_txn, ai, &err );
if(err == DB_LOCK_DEADLOCK) {
ldbm_nasty("ldbm_back_seq deadlock retry", 1600, err);
-#ifdef FIX_TXN_DEADLOCKS
-#error if txn != NULL, have to retry the entire transaction
-#endif
- continue;
+ if (txn.back_txn_txn) {
+ /* just in case */
+ slapi_ch_free(&(data.data));
+ if ((key.data != little_buffer) && (key.data != &keystring)) {
+ slapi_ch_free(&(key.data));
+ }
+ goto retry;
+ } else {
+ continue;
+ }
} else {
break;
}
}
}
+ } else {
+ if (txn.back_txn_txn) {
+ dblayer_read_txn_abort(be, &txn);
+ }
+ if (DB_LOCK_DEADLOCK == return_value) {
+ ldbm_nasty("ldbm_back_seq deadlock retry", 1601, err);
+ /* just in case */
+ slapi_ch_free(&(data.data));
+ if ((key.data != little_buffer) && (key.data != &keystring)) {
+ slapi_ch_free(&(key.data));
+ }
+ goto retry;
+ }
}
if(retry_count == IDL_FETCH_RETRY_COUNT) {
ldbm_nasty("ldbm_back_seq retry count exceeded",1645,err);
10 years, 2 months
Branch '389-ds-base-1.3.1' - ldap/servers
by Mark Reynolds
ldap/servers/plugins/replication/repl5.h | 8 +-
ldap/servers/plugins/replication/repl5_replica.c | 48 ++++++++----
ldap/servers/plugins/replication/repl5_replica_config.c | 60 ++++++++++++++--
3 files changed, 90 insertions(+), 26 deletions(-)
New commits:
commit b45fb4481ad2ab7824858d418ba09428191775a4
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Thu Feb 13 14:54:11 2014 -0500
Ticket 525 - Replication retry time attributes cannot be added
Bug Description: Trying to add nsds5ReplicaBackoffMin/nsds5ReplicaBackoffMax
to a replica entry results in an error 53.
Fix Description: Allow the adding & deleting of these attributes. Also changed
their type to slapi_counters so they can be safely updated.
https://fedorahosted.org/389/ticket/525
Reviewed by: nhosoi(Thanks!)
(cherry picked from commit 56e3a09e714f0b2bf38bdf92ba43242a52c748ba)
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index 655e8ba..4809441 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -597,10 +597,10 @@ void replica_update_state (time_t when, void *arg);
void replica_reset_csn_pl(Replica *r);
PRUint64 replica_get_protocol_timeout(Replica *r);
void replica_set_protocol_timeout(Replica *r, PRUint64 timeout);
-int replica_get_backoff_min(Replica *r);
-int replica_get_backoff_max(Replica *r);
-void replica_set_backoff_min(Replica *r, int min);
-void replica_set_backoff_max(Replica *r, int max);
+PRUint64 replica_get_backoff_min(Replica *r);
+PRUint64 replica_get_backoff_max(Replica *r);
+void replica_set_backoff_min(Replica *r, PRUint64 min);
+void replica_set_backoff_max(Replica *r, PRUint64 max);
/* The functions below handles the state flag */
/* Current internal state flags */
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
index 02d4e74..4992020 100644
--- a/ldap/servers/plugins/replication/repl5_replica.c
+++ b/ldap/servers/plugins/replication/repl5_replica.c
@@ -87,9 +87,9 @@ struct replica {
PRBool state_update_inprogress; /* replica state is being updated */
PRLock *agmt_lock; /* protects agreement creation, start and stop */
char *locking_purl; /* supplier who has exclusive access */
- Slapi_Counter *protocol_timeout; /* protocol shutdown timeout */
- PRUint64 backoff_min; /* backoff retry minimum */
- PRUint64 backoff_max; /* backoff retry maximum */
+ Slapi_Counter *protocol_timeout;/* protocol shutdown timeout */
+ Slapi_Counter *backoff_min; /* backoff retry minimum */
+ Slapi_Counter *backoff_max; /* backoff retry maximum */
};
@@ -208,7 +208,11 @@ replica_new_from_entry (Slapi_Entry *e, char *errortext, PRBool is_add_operation
rc = -1;
goto done;
}
+
+ /* init the slapi_counter/atomic settings */
r->protocol_timeout = slapi_counter_new();
+ r->backoff_min = slapi_counter_new();
+ r->backoff_max = slapi_counter_new();
/* read parameters from the replica config entry */
rc = _replica_init_from_config (r, e, errortext);
@@ -405,6 +409,8 @@ replica_destroy(void **arg)
}
slapi_counter_destroy(&r->protocol_timeout);
+ slapi_counter_destroy(&r->backoff_min);
+ slapi_counter_destroy(&r->backoff_max);
slapi_ch_free((void **)arg);
}
@@ -1739,11 +1745,11 @@ _replica_init_from_config (Replica *r, Slapi_Entry *e, char *errortext)
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Backoff minimum (%d) can not be greater than "
"the backoff maximum (%d). Using default values: min (%d) max (%d)\n", backoff_min, backoff_max,
PROTOCOL_BACKOFF_MINIMUM, PROTOCOL_BACKOFF_MAXIMUM);
- r->backoff_min = PROTOCOL_BACKOFF_MINIMUM;
- r->backoff_max = PROTOCOL_BACKOFF_MAXIMUM;
+ slapi_counter_set_value(r->backoff_min, PROTOCOL_BACKOFF_MINIMUM);
+ slapi_counter_set_value(r->backoff_max, PROTOCOL_BACKOFF_MAXIMUM);
} else {
- r->backoff_min = backoff_min;
- r->backoff_max = backoff_max;
+ slapi_counter_set_value(r->backoff_min, backoff_min);
+ slapi_counter_set_value(r->backoff_max, backoff_max);
}
/* get the protocol timeout */
@@ -3893,26 +3899,38 @@ replica_get_attr ( Slapi_PBlock *pb, const char* type, void *value )
return rc;
}
-int
+PRUint64
replica_get_backoff_min(Replica *r)
{
- return (int)r->backoff_min;
+ if(r){
+ return slapi_counter_get_value(r->backoff_min);
+ } else {
+ return PROTOCOL_BACKOFF_MINIMUM;
+ }
}
-int
+PRUint64
replica_get_backoff_max(Replica *r)
{
- return (int)r->backoff_max;
+ if(r){
+ return slapi_counter_get_value(r->backoff_max);
+ } else {
+ return PROTOCOL_BACKOFF_MAXIMUM;
+ }
}
void
-replica_set_backoff_min(Replica *r, int min)
+replica_set_backoff_min(Replica *r, PRUint64 min)
{
- r->backoff_min = min;
+ if(r){
+ slapi_counter_set_value(r->backoff_min, min);
+ }
}
void
-replica_set_backoff_max(Replica *r, int max)
+replica_set_backoff_max(Replica *r, PRUint64 max)
{
- r->backoff_max = max;
+ if(r){
+ slapi_counter_set_value(r->backoff_max, max);
+ }
}
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index fa324e9..4e5d4f1 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -373,8 +373,10 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
else if ((mods[i]->mod_op & LDAP_MOD_DELETE) || mods[i]->mod_bvalues == NULL
|| mods[i]->mod_bvalues[0]->bv_val == NULL)
{
- /* currently, you can only remove referral,
- legacy consumer or bind dn attribute */
+ /*
+ * Where possible/allowed return replica config settings to their
+ * default values.
+ */
if (strcasecmp (config_attr, attr_replicaBindDn) == 0)
{
*returncode = replica_config_change_updatedn (r, mods[i], errortext, apply_mods);
@@ -397,14 +399,24 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
strcasecmp (config_attr, type_replicaAbortCleanRUV) == 0)
{
/*
- * Only allow the deletion of the cleanAllRUV config attributes, and the
- * protocol timeout.
+ * Nothing to do in this case, allow it, and continue.
*/
continue;
}
else if (strcasecmp (config_attr, type_replicaProtocolTimeout) == 0 )
{
- replica_set_protocol_timeout(r, DEFAULT_PROTOCOL_TIMEOUT);
+ if (apply_mods)
+ replica_set_protocol_timeout(r, DEFAULT_PROTOCOL_TIMEOUT);
+ }
+ else if(strcasecmp (config_attr, type_replicaBackoffMin) == 0 )
+ {
+ if (apply_mods)
+ replica_set_backoff_min(r, PROTOCOL_BACKOFF_MINIMUM);
+ }
+ else if (strcasecmp (config_attr, type_replicaBackoffMax) == 0 )
+ {
+ if (apply_mods)
+ replica_set_backoff_max(r, PROTOCOL_BACKOFF_MAXIMUM);
}
else
{
@@ -497,10 +509,10 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
else if (strcasecmp (config_attr, type_replicaProtocolTimeout) == 0 ){
if (apply_mods)
{
- long ptimeout = 0;
+ PRUint64 ptimeout = 0;
if(config_attr_value){
- ptimeout = atol(config_attr_value);
+ ptimeout = atoll(config_attr_value);
}
if(ptimeout <= 0){
@@ -514,6 +526,40 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
replica_set_protocol_timeout(r, ptimeout);
}
}
+ else if(strcasecmp (config_attr, type_replicaBackoffMin) == 0 )
+ {
+ if (apply_mods)
+ {
+ PRUint64 val = atoll(config_attr_value);
+
+ if(val <= 0){
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
+ PR_snprintf (errortext, SLAPI_DSE_RETURNTEXT_SIZE,
+ "attribute %s value (%s) is invalid, must be a number greater than zero.\n",
+ config_attr, config_attr_value ? config_attr_value : "");
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_config_modify: %s\n", errortext);
+ break;
+ }
+ replica_set_backoff_min(r, val);
+ }
+ }
+ else if (strcasecmp (config_attr, type_replicaBackoffMax) == 0 )
+ {
+ if (apply_mods)
+ {
+ PRUint64 val = atoll(config_attr_value);
+
+ if(val <= 0){
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
+ PR_snprintf (errortext, SLAPI_DSE_RETURNTEXT_SIZE,
+ "attribute %s value (%s) is invalid, must be a number greater than zero.\n",
+ config_attr, config_attr_value ? config_attr_value : "");
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_config_modify: %s\n", errortext);
+ break;
+ }
+ replica_set_backoff_max(r, val);
+ }
+ }
else
{
*returncode = LDAP_UNWILLING_TO_PERFORM;
10 years, 2 months
Branch '389-ds-base-1.3.2' - ldap/servers
by Mark Reynolds
ldap/servers/plugins/replication/repl5.h | 8 +-
ldap/servers/plugins/replication/repl5_replica.c | 48 ++++++++----
ldap/servers/plugins/replication/repl5_replica_config.c | 60 ++++++++++++++--
3 files changed, 90 insertions(+), 26 deletions(-)
New commits:
commit 56e3a09e714f0b2bf38bdf92ba43242a52c748ba
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Thu Feb 13 14:54:11 2014 -0500
Ticket 525 - Replication retry time attributes cannot be added
Bug Description: Trying to add nsds5ReplicaBackoffMin/nsds5ReplicaBackoffMax
to a replica entry results in an error 53.
Fix Description: Allow the adding & deleting of these attributes. Also changed
their type to slapi_counters so they can be safely updated.
https://fedorahosted.org/389/ticket/525
Reviewed by: nhosoi(Thanks!)
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index 5383204..f841afe 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -602,10 +602,10 @@ void replica_update_state (time_t when, void *arg);
void replica_reset_csn_pl(Replica *r);
PRUint64 replica_get_protocol_timeout(Replica *r);
void replica_set_protocol_timeout(Replica *r, PRUint64 timeout);
-int replica_get_backoff_min(Replica *r);
-int replica_get_backoff_max(Replica *r);
-void replica_set_backoff_min(Replica *r, int min);
-void replica_set_backoff_max(Replica *r, int max);
+PRUint64 replica_get_backoff_min(Replica *r);
+PRUint64 replica_get_backoff_max(Replica *r);
+void replica_set_backoff_min(Replica *r, PRUint64 min);
+void replica_set_backoff_max(Replica *r, PRUint64 max);
/* The functions below handles the state flag */
/* Current internal state flags */
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
index f509bd4..9394eee 100644
--- a/ldap/servers/plugins/replication/repl5_replica.c
+++ b/ldap/servers/plugins/replication/repl5_replica.c
@@ -87,9 +87,9 @@ struct replica {
PRBool state_update_inprogress; /* replica state is being updated */
PRLock *agmt_lock; /* protects agreement creation, start and stop */
char *locking_purl; /* supplier who has exclusive access */
- Slapi_Counter *protocol_timeout; /* protocol shutdown timeout */
- PRUint64 backoff_min; /* backoff retry minimum */
- PRUint64 backoff_max; /* backoff retry maximum */
+ Slapi_Counter *protocol_timeout;/* protocol shutdown timeout */
+ Slapi_Counter *backoff_min; /* backoff retry minimum */
+ Slapi_Counter *backoff_max; /* backoff retry maximum */
};
@@ -208,7 +208,11 @@ replica_new_from_entry (Slapi_Entry *e, char *errortext, PRBool is_add_operation
rc = -1;
goto done;
}
+
+ /* init the slapi_counter/atomic settings */
r->protocol_timeout = slapi_counter_new();
+ r->backoff_min = slapi_counter_new();
+ r->backoff_max = slapi_counter_new();
/* read parameters from the replica config entry */
rc = _replica_init_from_config (r, e, errortext);
@@ -405,6 +409,8 @@ replica_destroy(void **arg)
}
slapi_counter_destroy(&r->protocol_timeout);
+ slapi_counter_destroy(&r->backoff_min);
+ slapi_counter_destroy(&r->backoff_max);
slapi_ch_free((void **)arg);
}
@@ -1769,11 +1775,11 @@ _replica_init_from_config (Replica *r, Slapi_Entry *e, char *errortext)
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Backoff minimum (%d) can not be greater than "
"the backoff maximum (%d). Using default values: min (%d) max (%d)\n", backoff_min, backoff_max,
PROTOCOL_BACKOFF_MINIMUM, PROTOCOL_BACKOFF_MAXIMUM);
- r->backoff_min = PROTOCOL_BACKOFF_MINIMUM;
- r->backoff_max = PROTOCOL_BACKOFF_MAXIMUM;
+ slapi_counter_set_value(r->backoff_min, PROTOCOL_BACKOFF_MINIMUM);
+ slapi_counter_set_value(r->backoff_max, PROTOCOL_BACKOFF_MAXIMUM);
} else {
- r->backoff_min = backoff_min;
- r->backoff_max = backoff_max;
+ slapi_counter_set_value(r->backoff_min, backoff_min);
+ slapi_counter_set_value(r->backoff_max, backoff_max);
}
/* get the protocol timeout */
@@ -3923,26 +3929,38 @@ replica_get_attr ( Slapi_PBlock *pb, const char* type, void *value )
return rc;
}
-int
+PRUint64
replica_get_backoff_min(Replica *r)
{
- return (int)r->backoff_min;
+ if(r){
+ return slapi_counter_get_value(r->backoff_min);
+ } else {
+ return PROTOCOL_BACKOFF_MINIMUM;
+ }
}
-int
+PRUint64
replica_get_backoff_max(Replica *r)
{
- return (int)r->backoff_max;
+ if(r){
+ return slapi_counter_get_value(r->backoff_max);
+ } else {
+ return PROTOCOL_BACKOFF_MAXIMUM;
+ }
}
void
-replica_set_backoff_min(Replica *r, int min)
+replica_set_backoff_min(Replica *r, PRUint64 min)
{
- r->backoff_min = min;
+ if(r){
+ slapi_counter_set_value(r->backoff_min, min);
+ }
}
void
-replica_set_backoff_max(Replica *r, int max)
+replica_set_backoff_max(Replica *r, PRUint64 max)
{
- r->backoff_max = max;
+ if(r){
+ slapi_counter_set_value(r->backoff_max, max);
+ }
}
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index 4e24c7b..9696134 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -374,8 +374,10 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
else if ((mods[i]->mod_op & LDAP_MOD_DELETE) || mods[i]->mod_bvalues == NULL
|| mods[i]->mod_bvalues[0]->bv_val == NULL)
{
- /* currently, you can only remove referral,
- legacy consumer or bind dn attribute */
+ /*
+ * Where possible/allowed return replica config settings to their
+ * default values.
+ */
if (strcasecmp (config_attr, attr_replicaBindDn) == 0)
{
*returncode = replica_config_change_updatedn (r, mods[i], errortext, apply_mods);
@@ -398,14 +400,24 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
strcasecmp (config_attr, type_replicaAbortCleanRUV) == 0)
{
/*
- * Only allow the deletion of the cleanAllRUV config attributes, and the
- * protocol timeout.
+ * Nothing to do in this case, allow it, and continue.
*/
continue;
}
else if (strcasecmp (config_attr, type_replicaProtocolTimeout) == 0 )
{
- replica_set_protocol_timeout(r, DEFAULT_PROTOCOL_TIMEOUT);
+ if (apply_mods)
+ replica_set_protocol_timeout(r, DEFAULT_PROTOCOL_TIMEOUT);
+ }
+ else if(strcasecmp (config_attr, type_replicaBackoffMin) == 0 )
+ {
+ if (apply_mods)
+ replica_set_backoff_min(r, PROTOCOL_BACKOFF_MINIMUM);
+ }
+ else if (strcasecmp (config_attr, type_replicaBackoffMax) == 0 )
+ {
+ if (apply_mods)
+ replica_set_backoff_max(r, PROTOCOL_BACKOFF_MAXIMUM);
}
else
{
@@ -498,10 +510,10 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
else if (strcasecmp (config_attr, type_replicaProtocolTimeout) == 0 ){
if (apply_mods)
{
- long ptimeout = 0;
+ PRUint64 ptimeout = 0;
if(config_attr_value){
- ptimeout = atol(config_attr_value);
+ ptimeout = atoll(config_attr_value);
}
if(ptimeout <= 0){
@@ -515,6 +527,40 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
replica_set_protocol_timeout(r, ptimeout);
}
}
+ else if(strcasecmp (config_attr, type_replicaBackoffMin) == 0 )
+ {
+ if (apply_mods)
+ {
+ PRUint64 val = atoll(config_attr_value);
+
+ if(val <= 0){
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
+ PR_snprintf (errortext, SLAPI_DSE_RETURNTEXT_SIZE,
+ "attribute %s value (%s) is invalid, must be a number greater than zero.\n",
+ config_attr, config_attr_value ? config_attr_value : "");
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_config_modify: %s\n", errortext);
+ break;
+ }
+ replica_set_backoff_min(r, val);
+ }
+ }
+ else if (strcasecmp (config_attr, type_replicaBackoffMax) == 0 )
+ {
+ if (apply_mods)
+ {
+ PRUint64 val = atoll(config_attr_value);
+
+ if(val <= 0){
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
+ PR_snprintf (errortext, SLAPI_DSE_RETURNTEXT_SIZE,
+ "attribute %s value (%s) is invalid, must be a number greater than zero.\n",
+ config_attr, config_attr_value ? config_attr_value : "");
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_config_modify: %s\n", errortext);
+ break;
+ }
+ replica_set_backoff_max(r, val);
+ }
+ }
else
{
*returncode = LDAP_UNWILLING_TO_PERFORM;
10 years, 2 months
ldap/servers
by Mark Reynolds
ldap/servers/plugins/replication/repl5.h | 8 +-
ldap/servers/plugins/replication/repl5_replica.c | 48 ++++++++----
ldap/servers/plugins/replication/repl5_replica_config.c | 60 ++++++++++++++--
3 files changed, 90 insertions(+), 26 deletions(-)
New commits:
commit dde9abef5ca71fc0557c66cabb99cb0a6f5e0332
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Thu Feb 13 14:54:11 2014 -0500
Ticket 525 - Replication retry time attributes cannot be added
Bug Description: Trying to add nsds5ReplicaBackoffMin/nsds5ReplicaBackoffMax
to a replica entry results in an error 53.
Fix Description: Allow the adding & deleting of these attributes. Also changed
their type to slapi_counters so they can be safely updated.
https://fedorahosted.org/389/ticket/525
Reviewed by: nhosoi(Thanks!)
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index 716da32..04d5a82 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -603,10 +603,10 @@ void replica_update_state (time_t when, void *arg);
void replica_reset_csn_pl(Replica *r);
PRUint64 replica_get_protocol_timeout(Replica *r);
void replica_set_protocol_timeout(Replica *r, PRUint64 timeout);
-int replica_get_backoff_min(Replica *r);
-int replica_get_backoff_max(Replica *r);
-void replica_set_backoff_min(Replica *r, int min);
-void replica_set_backoff_max(Replica *r, int max);
+PRUint64 replica_get_backoff_min(Replica *r);
+PRUint64 replica_get_backoff_max(Replica *r);
+void replica_set_backoff_min(Replica *r, PRUint64 min);
+void replica_set_backoff_max(Replica *r, PRUint64 max);
int replica_get_agmt_count(Replica *r);
void replica_incr_agmt_count(Replica *r);
void replica_decr_agmt_count(Replica *r);
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
index ffa5adc..3eeb322 100644
--- a/ldap/servers/plugins/replication/repl5_replica.c
+++ b/ldap/servers/plugins/replication/repl5_replica.c
@@ -87,9 +87,9 @@ struct replica {
PRBool state_update_inprogress; /* replica state is being updated */
PRLock *agmt_lock; /* protects agreement creation, start and stop */
char *locking_purl; /* supplier who has exclusive access */
- Slapi_Counter *protocol_timeout; /* protocol shutdown timeout */
- PRUint64 backoff_min; /* backoff retry minimum */
- PRUint64 backoff_max; /* backoff retry maximum */
+ Slapi_Counter *protocol_timeout;/* protocol shutdown timeout */
+ Slapi_Counter *backoff_min; /* backoff retry minimum */
+ Slapi_Counter *backoff_max; /* backoff retry maximum */
PRUint64 agmt_count; /* Number of agmts */
};
@@ -209,7 +209,11 @@ replica_new_from_entry (Slapi_Entry *e, char *errortext, PRBool is_add_operation
rc = -1;
goto done;
}
+
+ /* init the slapi_counter/atomic settings */
r->protocol_timeout = slapi_counter_new();
+ r->backoff_min = slapi_counter_new();
+ r->backoff_max = slapi_counter_new();
/* read parameters from the replica config entry */
rc = _replica_init_from_config (r, e, errortext);
@@ -406,6 +410,8 @@ replica_destroy(void **arg)
}
slapi_counter_destroy(&r->protocol_timeout);
+ slapi_counter_destroy(&r->backoff_min);
+ slapi_counter_destroy(&r->backoff_max);
slapi_ch_free((void **)arg);
}
@@ -1771,11 +1777,11 @@ _replica_init_from_config (Replica *r, Slapi_Entry *e, char *errortext)
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Backoff minimum (%d) can not be greater than "
"the backoff maximum (%d). Using default values: min (%d) max (%d)\n", backoff_min, backoff_max,
PROTOCOL_BACKOFF_MINIMUM, PROTOCOL_BACKOFF_MAXIMUM);
- r->backoff_min = PROTOCOL_BACKOFF_MINIMUM;
- r->backoff_max = PROTOCOL_BACKOFF_MAXIMUM;
+ slapi_counter_set_value(r->backoff_min, PROTOCOL_BACKOFF_MINIMUM);
+ slapi_counter_set_value(r->backoff_max, PROTOCOL_BACKOFF_MAXIMUM);
} else {
- r->backoff_min = backoff_min;
- r->backoff_max = backoff_max;
+ slapi_counter_set_value(r->backoff_min, backoff_min);
+ slapi_counter_set_value(r->backoff_max, backoff_max);
}
/* get the protocol timeout */
@@ -3930,28 +3936,40 @@ replica_get_attr ( Slapi_PBlock *pb, const char* type, void *value )
return rc;
}
-int
+PRUint64
replica_get_backoff_min(Replica *r)
{
- return (int)r->backoff_min;
+ if(r){
+ return slapi_counter_get_value(r->backoff_min);
+ } else {
+ return PROTOCOL_BACKOFF_MINIMUM;
+ }
}
-int
+PRUint64
replica_get_backoff_max(Replica *r)
{
- return (int)r->backoff_max;
+ if(r){
+ return slapi_counter_get_value(r->backoff_max);
+ } else {
+ return PROTOCOL_BACKOFF_MAXIMUM;
+ }
}
void
-replica_set_backoff_min(Replica *r, int min)
+replica_set_backoff_min(Replica *r, PRUint64 min)
{
- r->backoff_min = min;
+ if(r){
+ slapi_counter_set_value(r->backoff_min, min);
+ }
}
void
-replica_set_backoff_max(Replica *r, int max)
+replica_set_backoff_max(Replica *r, PRUint64 max)
{
- r->backoff_max = max;
+ if(r){
+ slapi_counter_set_value(r->backoff_max, max);
+ }
}
int
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index dfe898a..b1c700e 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -374,8 +374,10 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
else if ((mods[i]->mod_op & LDAP_MOD_DELETE) || mods[i]->mod_bvalues == NULL
|| mods[i]->mod_bvalues[0]->bv_val == NULL)
{
- /* currently, you can only remove referral,
- legacy consumer or bind dn attribute */
+ /*
+ * Where possible/allowed return replica config settings to their
+ * default values.
+ */
if (strcasecmp (config_attr, attr_replicaBindDn) == 0)
{
*returncode = replica_config_change_updatedn (r, mods[i], errortext, apply_mods);
@@ -398,14 +400,24 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
strcasecmp (config_attr, type_replicaAbortCleanRUV) == 0)
{
/*
- * Only allow the deletion of the cleanAllRUV config attributes, and the
- * protocol timeout.
+ * Nothing to do in this case, allow it, and continue.
*/
continue;
}
else if (strcasecmp (config_attr, type_replicaProtocolTimeout) == 0 )
{
- replica_set_protocol_timeout(r, DEFAULT_PROTOCOL_TIMEOUT);
+ if (apply_mods)
+ replica_set_protocol_timeout(r, DEFAULT_PROTOCOL_TIMEOUT);
+ }
+ else if(strcasecmp (config_attr, type_replicaBackoffMin) == 0 )
+ {
+ if (apply_mods)
+ replica_set_backoff_min(r, PROTOCOL_BACKOFF_MINIMUM);
+ }
+ else if (strcasecmp (config_attr, type_replicaBackoffMax) == 0 )
+ {
+ if (apply_mods)
+ replica_set_backoff_max(r, PROTOCOL_BACKOFF_MAXIMUM);
}
else
{
@@ -498,10 +510,10 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
else if (strcasecmp (config_attr, type_replicaProtocolTimeout) == 0 ){
if (apply_mods)
{
- long ptimeout = 0;
+ PRUint64 ptimeout = 0;
if(config_attr_value){
- ptimeout = atol(config_attr_value);
+ ptimeout = atoll(config_attr_value);
}
if(ptimeout <= 0){
@@ -515,6 +527,40 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
replica_set_protocol_timeout(r, ptimeout);
}
}
+ else if(strcasecmp (config_attr, type_replicaBackoffMin) == 0 )
+ {
+ if (apply_mods)
+ {
+ PRUint64 val = atoll(config_attr_value);
+
+ if(val <= 0){
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
+ PR_snprintf (errortext, SLAPI_DSE_RETURNTEXT_SIZE,
+ "attribute %s value (%s) is invalid, must be a number greater than zero.\n",
+ config_attr, config_attr_value ? config_attr_value : "");
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_config_modify: %s\n", errortext);
+ break;
+ }
+ replica_set_backoff_min(r, val);
+ }
+ }
+ else if (strcasecmp (config_attr, type_replicaBackoffMax) == 0 )
+ {
+ if (apply_mods)
+ {
+ PRUint64 val = atoll(config_attr_value);
+
+ if(val <= 0){
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
+ PR_snprintf (errortext, SLAPI_DSE_RETURNTEXT_SIZE,
+ "attribute %s value (%s) is invalid, must be a number greater than zero.\n",
+ config_attr, config_attr_value ? config_attr_value : "");
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_config_modify: %s\n", errortext);
+ break;
+ }
+ replica_set_backoff_max(r, val);
+ }
+ }
else
{
*returncode = LDAP_UNWILLING_TO_PERFORM;
10 years, 2 months
ldap/admin
by Mark Reynolds
ldap/admin/src/logconv.pl | 92 +++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 82 insertions(+), 10 deletions(-)
New commits:
commit 09f55fc4065d8104192e11817ffd62a16b178654
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Thu Feb 13 10:14:38 2014 -0500
Ticket 47552 - logconv: unindexed report should list bind dn
Description: Add the bind DN to the unindexed search report. We need
to adjust the hash key in order to find the correct bind DN.
Updated the unindexed summary report to expand on each filter,
and the bind DN that issued it. As well as each bind DN that
issused a unindexed search, and all the filters that bind DN
used.
Also, when doing a unindexed report, always grab the IP address
regardless if the connection stat flag is set.
Also made a minor improvement to the log count in the processing
output.
https://fedorahosted.org/389/ticket/47552
Reviewed by: rmeggins(Thanks!)
diff --git a/ldap/admin/src/logconv.pl b/ldap/admin/src/logconv.pl
index d7bfb2a..c835e1a 100755
--- a/ldap/admin/src/logconv.pl
+++ b/ldap/admin/src/logconv.pl
@@ -432,11 +432,11 @@ for (my $count=0; $count < $file_count; $count++){
next;
}
$linesProcessed = 0; $lineBlockCount = 0;
- $logCount--;
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$atime,$mtime,$ctime,$blksize,$blocks);
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$cursize,
$atime,$mtime,$ctime,$blksize,$blocks) = stat($logname);
print sprintf "[%03d] %-30s\tsize (bytes): %12s\n",$logCount, $logname, $cursize;
+ $logCount--;
my $tar = 0;
my $tariter = 0;
@@ -735,13 +735,19 @@ if ($verb eq "yes" || $usage =~ /u/ || $usage =~ /U/){
my $base_conn_op = $hashes->{base_conn_op};
my $scope_conn_op = $hashes->{scope_conn_op};
my $filter_conn_op = $hashes->{filter_conn_op};
+ my $bind_conn_op = $hashes->{bind_conn_op};
my $notesCount = 1;
my $unindexedIp;
+ my $binddn_key;
my %uniqFilt = (); # hash of unique filters
+ my %uniqFilter = (); # hash of unique filters bind dn
+ my %uniqBindDNs = (); # hash of unique bind dn's
+ my %uniqBindFilters = (); # hash of filters for a bind DN
+
while (my ($srcnt_conn_op, $count) = each %{$notesa_conn_op}) {
+ my ($srvRstCnt, $conn, $op) = split(",", $srcnt_conn_op);
if ($verb eq "yes" || $usage =~ /u/) {
- my ($srvRstCnt, $conn, $op) = split(",", $srcnt_conn_op);
my $unindexedIp = getIPfromConn($conn, $srvRstCnt);
print "\n Unindexed Search #".$notesCount." (notes=A)\n";
print " - Date/Time: $time_conn_op->{$srcnt_conn_op}\n";
@@ -763,13 +769,43 @@ if ($verb eq "yes" || $usage =~ /u/ || $usage =~ /U/){
}
$uniqFilt{$filter_conn_op->{$srcnt_conn_op}}++;
}
+ while($op > 0){
+ # The bind op is not the same as the search op that triggered the notes=A.
+ # We have adjust the key by decrementing the op count until we find the last bind op.
+ $op--;
+ $binddn_key = "$srvRstCnt,$conn,$op";
+ if (exists($bind_conn_op->{$binddn_key}) && defined($bind_conn_op->{$binddn_key})) {
+ if ($verb eq "yes" || $usage =~ /u/) {
+ print " - Bind DN: $bind_conn_op->{$binddn_key}\n";
+ }
+ $uniqBindDNs{$bind_conn_op->{$binddn_key}}++;
+ if( $uniqFilt{$filter_conn_op->{$srcnt_conn_op}} && defined($filter_conn_op->{$srcnt_conn_op})) {
+ $uniqBindFilters{$bind_conn_op->{$binddn_key}}{$filter_conn_op->{$srcnt_conn_op}}++;
+ $uniqFilter{$filter_conn_op->{$srcnt_conn_op}}{$bind_conn_op->{$binddn_key}}++;
+ }
+ last;
+ }
+ }
$notesCount++;
}
if ($usage =~ /U/) {
- print "\n Unindexed Search Summary - $notesCount total unindexed searches\n";
+ $notesCount--;
+ print "\n Unindexed Search Summary - $notesCount total unindexed searches";
foreach my $key (sort { $uniqFilt{$b} <=> $uniqFilt{$a} } keys %uniqFilt) {
if ($uniqFilt{$key} > 0) {
- printf " - Number of times used unindexed: %10d Filter: $key\n", $uniqFilt{$key};
+ printf "\n - Unindexed Filters: Filter: $key (occurrences $uniqFilt{$key})\n";
+ foreach my $bindkey (sort { $uniqFilter{$key}{$a} <=> $uniqFilter{$key}{$b} } keys %{$uniqFilter{$key}} ) {
+ printf " - Bind DN: $bindkey (binds $uniqFilter{$key}{$bindkey})\n";
+ }
+ }
+ }
+ # now list the binds, and their filters
+ foreach my $key (sort { $uniqBindDNs{$b} <=> $uniqBindDNs{$a} } keys %uniqBindDNs) {
+ if ($uniqBindDNs{$key} > 0) {
+ printf "\n - Unindexed Bind DNs: Bind DN: $key (binds $uniqBindDNs{$key})\n";
+ foreach my $bindkey (sort { $uniqBindFilters{$key}{$a} <=> $uniqBindFilters{$key}{$b} } keys %{$uniqBindFilters{$key}} ) {
+ printf " - Unindexed Filter: $bindkey (occurrances $uniqBindFilters{$key}{$bindkey})\n";
+ }
}
}
}
@@ -783,13 +819,19 @@ if ($verb eq "yes" || $usage =~ /u/ || $usage =~ /U/){
my $base_conn_op = $hashes->{base_conn_op};
my $scope_conn_op = $hashes->{scope_conn_op};
my $filter_conn_op = $hashes->{filter_conn_op};
+ my $bind_conn_op = $hashes->{bind_conn_op};
my $notesCount = 1;
my $unindexedIp;
+ my $binddn_key;
my %uniqFilt = (); # hash of unique filters
+ my %uniqFilter = (); # hash of unique filters bind dn
+ my %uniqBindDNs = (); # hash of unique bind dn's
+ my %uniqBindFilters = (); # hash of filters for a bind DN
+
while (my ($srcnt_conn_op, $count) = each %{$notesu_conn_op}) {
+ my ($srvRstCnt, $conn, $op) = split(",", $srcnt_conn_op);
if ($verb eq "yes" || $usage =~ /u/) {
- my ($srvRstCnt, $conn, $op) = split(",", $srcnt_conn_op);
$unindexedIp = getIPfromConn($conn, $srvRstCnt);
print "\n Unindexed Component #".$notesCount." (notes=U)\n";
print " - Date/Time: $time_conn_op->{$srcnt_conn_op}\n";
@@ -811,13 +853,43 @@ if ($verb eq "yes" || $usage =~ /u/ || $usage =~ /U/){
}
$uniqFilt{$filter_conn_op->{$srcnt_conn_op}}++;
}
+ while($op > 0){
+ # The bind op is not the same as the search op that triggered the notes=U.
+ # We have adjust the key by decrementing the op count until we find the last bind op.
+ $op--;
+ $binddn_key = "$srvRstCnt,$conn,$op";
+ if (exists($bind_conn_op->{$binddn_key}) && defined($bind_conn_op->{$binddn_key})) {
+ if ($verb eq "yes" || $usage =~ /u/) {
+ print " - Bind DN: $bind_conn_op->{$binddn_key}\n";
+ }
+ $uniqBindDNs{$bind_conn_op->{$binddn_key}}++;
+ if( $uniqFilt{$filter_conn_op->{$srcnt_conn_op}} && defined($filter_conn_op->{$srcnt_conn_op})) {
+ $uniqBindFilters{$bind_conn_op->{$binddn_key}}{$filter_conn_op->{$srcnt_conn_op}}++;
+ $uniqFilter{$filter_conn_op->{$srcnt_conn_op}}{$bind_conn_op->{$binddn_key}}++;
+ }
+ last;
+ }
+ }
$notesCount++;
}
if ($usage =~ /U/) {
- print "\n Unindexed Component Summary - $notesCount total unindexed components\n";
+ $notesCount--;
+ print "\n Unindexed Component Summary - $notesCount total unindexed components";
foreach my $key (sort { $uniqFilt{$b} <=> $uniqFilt{$a} } keys %uniqFilt) {
if ($uniqFilt{$key} > 0) {
- printf " - Number of times used unindexed: %10d Filter: $key\n", $uniqFilt{$key};
+ printf "\n - Unindexed Filters: Filter: $key (occurrences $uniqFilt{$key})\n";
+ foreach my $bindkey (sort { $uniqFilter{$key}{$a} <=> $uniqFilter{$key}{$b} } keys %{$uniqFilter{$key}} ) {
+ printf " - Bind DN: $bindkey (binds $uniqFilter{$key}{$bindkey})\n";
+ }
+ }
+ }
+ # now list the binds, and their filters
+ foreach my $key (sort { $uniqBindDNs{$b} <=> $uniqBindDNs{$a} } keys %uniqBindDNs) {
+ if ($uniqBindDNs{$key} > 0) {
+ printf "\n - Unindexed Bind DNs: Bind DN: $key (binds $uniqBindDNs{$key})\n";
+ foreach my $bindkey (sort { $uniqBindFilters{$key}{$a} <=> $uniqBindFilters{$key}{$b} } keys %{$uniqBindFilters{$key}} ) {
+ printf " - Unindexed Filter: $bindkey (occurrances $uniqBindFilters{$key}{$bindkey})\n";
+ }
}
}
}
@@ -1867,13 +1939,13 @@ sub parseLineNormal
$tmpp = $binddn;
$tmpp =~ tr/A-Z/a-z/;
$hashes->{bindlist}->{$tmpp}++;
- if($usage =~ /f/ || $verb eq "yes"){
+ if($usage =~ /f/ || $usage =~ /u/ || $usage =~ /U/ || $verb eq "yes"){
$hashes->{bind_conn_op}->{"$serverRestartCount,$conn,$op"} = $tmpp;
}
} else {
$anonymousBindCount++;
$hashes->{bindlist}->{"Anonymous Binds"}++;
- if($usage =~ /f/ || $verb eq "yes"){
+ if($usage =~ /f/ || $usage =~ /u/ || $usage =~ /U/ || $verb eq "yes"){
$hashes->{bind_conn_op}->{"$serverRestartCount,$conn,$op"} = "";
}
inc_stats('anonbind',$s_stats,$m_stats);
@@ -1987,7 +2059,7 @@ sub parseLineNormal
elsif (m/- U1/){ $hashes->{rsrc}->{"U1"}++; }
else { $hashes->{rsrc}->{"other"}++; }
}
- if ($usage =~ /g/ || $usage =~ /c/ || $usage =~ /i/ || $usage =~ /f/ || $verb eq "yes"){
+ if ($usage =~ /g/ || $usage =~ /c/ || $usage =~ /i/ || $usage =~ /f/ || $usage =~ /u/ || $usage =~ /U/ || $verb eq "yes"){
$exc = "no";
if ($_ =~ /connection from *([0-9A-fa-f\.\:]+)/i ) {
for (my $xxx = 0; $xxx < $#excludeIP; $xxx++){
10 years, 2 months
dirsrvtests/tickets ldap/servers
by thierry bordaz
dirsrvtests/tickets/ticket47619_test.py | 299 ++++++++++++++++++++++++++++++++
ldap/servers/plugins/retrocl/retrocl.c | 3
2 files changed, 302 insertions(+)
New commits:
commit 8087f058cd9acc304de351412742fd8ceb3ceb48
Author: Thierry bordaz (tbordaz) <tbordaz(a)redhat.com>
Date: Wed Jan 15 09:59:13 2014 +0100
Ticket 47619: cannot reindex retrochangelog
Bug Description:
An index task (through db2index.pl) on changelog backend may hang.
The reason is that the retrocl-plugin start function (retrocl_start) acquires the
changelog backend in read (slapi_be_Rlock) but does not release it.
The task will try to acquire it in Write but will wait indefinitely.
Fix Description:
Make retrocl_start to release the lock acquired in Read in slapi_mapping_tree_select
https://fedorahosted.org/389/ticket/47619
Reviewed by: Rich Megginson
Platforms tested: F17
Flag Day: no
Doc impact: no
diff --git a/dirsrvtests/tickets/ticket47619_test.py b/dirsrvtests/tickets/ticket47619_test.py
new file mode 100644
index 0000000..c3eae8d
--- /dev/null
+++ b/dirsrvtests/tickets/ticket47619_test.py
@@ -0,0 +1,299 @@
+'''
+Created on Nov 7, 2013
+
+@author: tbordaz
+'''
+import os
+import sys
+import time
+import ldap
+import logging
+import socket
+import time
+import logging
+import pytest
+import re
+from lib389 import DirSrv, Entry, tools
+from lib389.tools import DirSrvTools
+from lib389._constants import *
+from lib389.properties import *
+from constants import *
+
+logging.getLogger(__name__).setLevel(logging.DEBUG)
+log = logging.getLogger(__name__)
+
+installation_prefix = None
+
+TEST_REPL_DN = "cn=test_repl, %s" % SUFFIX
+ENTRY_DN = "cn=test_entry, %s" % SUFFIX
+
+OTHER_NAME = 'other_entry'
+MAX_OTHERS = 100
+
+ATTRIBUTES = [ 'street', 'countryName', 'description', 'postalAddress', 'postalCode', 'title', 'l', 'roomNumber' ]
+
+class TopologyMasterConsumer(object):
+ def __init__(self, master, consumer):
+ master.open()
+ self.master = master
+
+ consumer.open()
+ self.consumer = consumer
+
+ def __repr__(self):
+ return "Master[%s] -> Consumer[%s" % (self.master, self.consumer)
+
+
+(a)pytest.fixture(scope="module")
+def topology(request):
+ '''
+ This fixture is used to create a replicated topology for the 'module'.
+ The replicated topology is MASTER -> Consumer.
+ At the beginning, It may exists a master instance and/or a consumer instance.
+ It may also exists a backup for the master and/or the consumer.
+
+ Principle:
+ If master instance exists:
+ restart it
+ If consumer instance exists:
+ restart it
+ If backup of master AND backup of consumer exists:
+ create or rebind to consumer
+ create or rebind to master
+
+ restore master from backup
+ restore consumer from backup
+ else:
+ Cleanup everything
+ remove instances
+ remove backups
+ Create instances
+ Initialize replication
+ Create backups
+ '''
+ global installation_prefix
+
+ if installation_prefix:
+ args_instance[SER_DEPLOYED_DIR] = installation_prefix
+
+ master = DirSrv(verbose=False)
+ consumer = DirSrv(verbose=False)
+
+ # Args for the master instance
+ args_instance[SER_HOST] = HOST_MASTER
+ args_instance[SER_PORT] = PORT_MASTER
+ args_instance[SER_SERVERID_PROP] = SERVERID_MASTER
+ args_master = args_instance.copy()
+ master.allocate(args_master)
+
+ # Args for the consumer instance
+ args_instance[SER_HOST] = HOST_CONSUMER
+ args_instance[SER_PORT] = PORT_CONSUMER
+ args_instance[SER_SERVERID_PROP] = SERVERID_CONSUMER
+ args_consumer = args_instance.copy()
+ consumer.allocate(args_consumer)
+
+
+ # Get the status of the backups
+ backup_master = master.checkBackupFS()
+ backup_consumer = consumer.checkBackupFS()
+
+ # Get the status of the instance and restart it if it exists
+ instance_master = master.exists()
+ if instance_master:
+ master.stop(timeout=10)
+ master.start(timeout=10)
+
+ instance_consumer = consumer.exists()
+ if instance_consumer:
+ consumer.stop(timeout=10)
+ consumer.start(timeout=10)
+
+ if backup_master and backup_consumer:
+ # The backups exist, assuming they are correct
+ # we just re-init the instances with them
+ if not instance_master:
+ master.create()
+ # Used to retrieve configuration information (dbdir, confdir...)
+ master.open()
+
+ if not instance_consumer:
+ consumer.create()
+ # Used to retrieve configuration information (dbdir, confdir...)
+ consumer.open()
+
+ # restore master from backup
+ master.stop(timeout=10)
+ master.restoreFS(backup_master)
+ master.start(timeout=10)
+
+ # restore consumer from backup
+ consumer.stop(timeout=10)
+ consumer.restoreFS(backup_consumer)
+ consumer.start(timeout=10)
+ else:
+ # We should be here only in two conditions
+ # - This is the first time a test involve master-consumer
+ # so we need to create everything
+ # - Something weird happened (instance/backup destroyed)
+ # so we discard everything and recreate all
+
+ # Remove all the backups. So even if we have a specific backup file
+ # (e.g backup_master) we clear all backups that an instance my have created
+ if backup_master:
+ master.clearBackupFS()
+ if backup_consumer:
+ consumer.clearBackupFS()
+
+ # Remove all the instances
+ if instance_master:
+ master.delete()
+ if instance_consumer:
+ consumer.delete()
+
+ # Create the instances
+ master.create()
+ master.open()
+ consumer.create()
+ consumer.open()
+
+ #
+ # Now prepare the Master-Consumer topology
+ #
+ # First Enable replication
+ master.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER)
+ consumer.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_CONSUMER)
+
+ # Initialize the supplier->consumer
+
+ properties = {RA_NAME: r'meTo_$host:$port',
+ RA_BINDDN: defaultProperties[REPLICATION_BIND_DN],
+ RA_BINDPW: defaultProperties[REPLICATION_BIND_PW],
+ RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD],
+ RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
+ repl_agreement = master.agreement.create(suffix=SUFFIX, host=consumer.host, port=consumer.port, properties=properties)
+
+ if not repl_agreement:
+ log.fatal("Fail to create a replica agreement")
+ sys.exit(1)
+
+ log.debug("%s created" % repl_agreement)
+ master.agreement.init(SUFFIX, HOST_CONSUMER, PORT_CONSUMER)
+ master.waitForReplInit(repl_agreement)
+
+ # Check replication is working fine
+ master.add_s(Entry((TEST_REPL_DN, {
+ 'objectclass': "top person".split(),
+ 'sn': 'test_repl',
+ 'cn': 'test_repl'})))
+ loop = 0
+ while loop <= 10:
+ try:
+ ent = consumer.getEntry(TEST_REPL_DN, ldap.SCOPE_BASE, "(objectclass=*)")
+ break
+ except ldap.NO_SUCH_OBJECT:
+ time.sleep(1)
+ loop += 1
+
+ # Time to create the backups
+ master.stop(timeout=10)
+ master.backupfile = master.backupFS()
+ master.start(timeout=10)
+
+ consumer.stop(timeout=10)
+ consumer.backupfile = consumer.backupFS()
+ consumer.start(timeout=10)
+
+ #
+ # Here we have two instances master and consumer
+ # with replication working. Either coming from a backup recovery
+ # or from a fresh (re)init
+ # Time to return the topology
+ return TopologyMasterConsumer(master, consumer)
+
+
+def test_ticket47619_init(topology):
+ """
+ Initialize the test environment
+ """
+ topology.master.plugins.enable(name=PLUGIN_RETRO_CHANGELOG)
+ #topology.master.plugins.enable(name=PLUGIN_MEMBER_OF)
+ #topology.master.plugins.enable(name=PLUGIN_REFER_INTEGRITY)
+ topology.master.stop(timeout=10)
+ topology.master.start(timeout=10)
+
+ topology.master.log.info("test_ticket47619_init topology %r" % (topology))
+ # the test case will check if a warning message is logged in the
+ # error log of the supplier
+ topology.master.errorlog_file = open(topology.master.errlog, "r")
+
+
+ # add dummy entries
+ for cpt in range(MAX_OTHERS):
+ name = "%s%d" % (OTHER_NAME, cpt)
+ topology.master.add_s(Entry(("cn=%s,%s" % (name, SUFFIX), {
+ 'objectclass': "top person".split(),
+ 'sn': name,
+ 'cn': name})))
+
+ topology.master.log.info("test_ticket47619_init: %d entries ADDed %s[0..%d]" % (MAX_OTHERS, OTHER_NAME, MAX_OTHERS-1))
+
+ # Check the number of entries in the retro changelog
+ time.sleep(2)
+ ents = topology.master.search_s(RETROCL_SUFFIX, ldap.SCOPE_ONELEVEL, "(objectclass=*)")
+ assert len(ents) == MAX_OTHERS
+
+def test_ticket47619_create_index(topology):
+
+ args = {INDEX_TYPE: 'eq'}
+ for attr in ATTRIBUTES:
+ topology.master.index.create(suffix=RETROCL_SUFFIX, attr=attr, args=args)
+
+def test_ticket47619_reindex(topology):
+ '''
+ Reindex all the attributes in ATTRIBUTES
+ '''
+ args = {TASK_WAIT: True,
+ TASK_TIMEOUT: 10}
+ for attr in ATTRIBUTES:
+ rc = topology.master.tasks.reindex(suffix=RETROCL_SUFFIX, attrname=attr, args=args)
+ assert rc == 0
+
+def test_ticket47619_check_indexed_search(topology):
+ for attr in ATTRIBUTES:
+ ents = topology.master.search_s(RETROCL_SUFFIX, ldap.SCOPE_SUBTREE, "(%s=hello)" % attr)
+ assert len(ents) == 0
+
+def test_ticket47619_final(topology):
+ topology.master.stop(timeout=10)
+ topology.consumer.stop(timeout=10)
+
+def run_isolated():
+ '''
+ run_isolated is used to run these test cases independently of a test scheduler (xunit, py.test..)
+ To run isolated without py.test, you need to
+ - edit this file and comment '@pytest.fixture' line before 'topology' function.
+ - set the installation prefix
+ - run this program
+ '''
+ global installation_prefix
+ installation_prefix = None
+
+ topo = topology(True)
+ test_ticket47619_init(topo)
+
+ test_ticket47619_create_index(topo)
+
+ # important restart that trigger the hang
+ # at restart, finding the new 'changelog' backend, the backend is acquired in Read
+ # preventing the reindex task to complete
+ topo.master.restart(timeout=10)
+ test_ticket47619_reindex(topo)
+ test_ticket47619_check_indexed_search(topo)
+
+ test_ticket47619_final(topo)
+
+
+if __name__ == '__main__':
+ run_isolated()
+
diff --git a/ldap/servers/plugins/retrocl/retrocl.c b/ldap/servers/plugins/retrocl/retrocl.c
index 7efe6c3..af410f0 100644
--- a/ldap/servers/plugins/retrocl/retrocl.c
+++ b/ldap/servers/plugins/retrocl/retrocl.c
@@ -258,6 +258,9 @@ static int retrocl_select_backend(void)
retrocl_create_cle();
slapi_pblock_destroy(pb);
+
+ if (be)
+ slapi_be_Unlock(be);
return retrocl_get_changenumbers();
}
10 years, 2 months