ldap/servers/plugins/replication/replutil.c | 12 ++-
ldap/servers/slapd/mapping_tree.c | 96 ++++++++++++++++++++++++----
ldap/servers/slapd/slapi-plugin.h | 5 +
ldap/servers/slapd/slapi-private.h | 3
4 files changed, 100 insertions(+), 16 deletions(-)
New commits:
commit 8c216a99cc752e6be2d73fd91a446f9d1d44a701
Author: Ludwig Krispenz <lkrispen(a)redhat.com>
Date: Fri Sep 13 10:03:31 2013 +0200
Use defines for backend error handling
diff --git a/ldap/servers/plugins/replication/replutil.c
b/ldap/servers/plugins/replication/replutil.c
index 4dee4c1..a567832 100644
--- a/ldap/servers/plugins/replication/replutil.c
+++ b/ldap/servers/plugins/replication/replutil.c
@@ -947,9 +947,9 @@ repl_chain_on_update(Slapi_PBlock *pb, Slapi_DN * target_dn,
if (root_mode == CHAIN_ROOT_UPDATE_LOCAL)
return local_backend;
else if (root_mode == CHAIN_ROOT_UPDATE_REJECT)
- return (-2);
+ return (SLAPI_BE_NO_BACKEND);
else if (root_mode == CHAIN_ROOT_UPDATE_REFERRAL)
- return (-3);
+ return (SLAPI_BE_REMOTE_BACKEND);
}
/* if the operation is a replicated operation
diff --git a/ldap/servers/slapd/mapping_tree.c b/ldap/servers/slapd/mapping_tree.c
index 53df04a..d0801e7 100644
--- a/ldap/servers/slapd/mapping_tree.c
+++ b/ldap/servers/slapd/mapping_tree.c
@@ -2572,7 +2572,7 @@ mtn_get_be_distributed(Slapi_PBlock *pb, mapping_tree_node *
target_node,
}
/* check if distribution plugi returned a special mode for
* updates as root */
- else if (index == -2 || index == -3)
+ else if (index == SLAPI_BE_NO_BACKEND || index == SLAPI_BE_REMOTE_BACKEND)
{
/* nothing special to do */
}
@@ -2686,17 +2686,17 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock
*pb,
} else {
*index = mtn_get_be_distributed(pb, target_node,
target_sdn, &flag_stop);
- if (*index == -2)
+ if (*index == SLAPI_BE_NO_BACKEND)
result = LDAP_UNWILLING_TO_PERFORM;
}
}
- if (*index == -3) {
+ if (*index == SLAPI_BE_REMOTE_BACKEND) {
*be = NULL;
*referral = (target_node->mtn_referral_entry ?
slapi_entry_dup(target_node->mtn_referral_entry) :
NULL);
(*index)++;
- }else if ((*index == -2) || (*index >= target_node->mtn_be_count)) {
+ }else if ((*index == SLAPI_BE_NO_BACKEND) || (*index >=
target_node->mtn_be_count)) {
/* we have already returned all backends -> return NULL */
*be = NULL;
*referral = NULL;
@@ -2739,7 +2739,7 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock
*pb,
*be = defbackend_get_backend();
}
if (flag_stop)
- *index = -2;
+ *index = SLAPI_BE_NO_BACKEND;
else
(*index)++;
}
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 6cb6d74..233dbe9 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -6163,8 +6163,13 @@ int slapi_unregister_backend_state_change(void * handle);
/* SLAPI_BE_ALL_BACKENDS is a special value that is returned by
* a distribution plugin function to indicate that all backends
* should be searched (it is only used for search operations).
+ *
+ * SLAPI_BE_NO_BACKEND indicates no more backend is available or allowed
+ * SLAPI_BE_REMOTE_BACKEND indicates that the are not locally available
*/
#define SLAPI_BE_ALL_BACKENDS -1
+#define SLAPI_BE_NO_BACKEND -2
+#define SLAPI_BE_REMOTE_BACKEND -3
commit b2ece76189f87f75ef16ae9c75fc4348904a6714
Author: Ludwig Krispenz <lkrispen(a)redhat.com>
Date: Wed Sep 11 14:42:36 2013 +0200
Ticket 314 - ChaiOnUpdate for root handling
Bug Description: If chaining and distribution are configured
updates as root are always applied locally
This leads to inconsistent data
Fix Description: Add a configuration option to control the
processing of root updates. Valid options are:
- local: apply changes to the local database
- reject: do not handle root updates
- referral: return the referral to the
chaining backend
https://fedorahosted.org/389/ticket/314
Reviewed by: ?
diff --git a/ldap/servers/plugins/replication/replutil.c
b/ldap/servers/plugins/replication/replutil.c
index d007f6c..4dee4c1 100644
--- a/ldap/servers/plugins/replication/replutil.c
+++ b/ldap/servers/plugins/replication/replutil.c
@@ -814,7 +814,8 @@ repl_set_mtn_state_and_referrals(
int
repl_chain_on_update(Slapi_PBlock *pb, Slapi_DN * target_dn,
char **mtn_be_names, int be_count,
- Slapi_DN * node_dn, int *mtn_be_states)
+ Slapi_DN * node_dn, int *mtn_be_states,
+ int root_mode)
{
char * requestor_dn;
unsigned long op_type;
@@ -943,7 +944,12 @@ repl_chain_on_update(Slapi_PBlock *pb, Slapi_DN * target_dn,
"is root: using local backend\n", connid, opid);
}
#endif
- return local_backend;
+ if (root_mode == CHAIN_ROOT_UPDATE_LOCAL)
+ return local_backend;
+ else if (root_mode == CHAIN_ROOT_UPDATE_REJECT)
+ return (-2);
+ else if (root_mode == CHAIN_ROOT_UPDATE_REFERRAL)
+ return (-3);
}
/* if the operation is a replicated operation
@@ -981,7 +987,7 @@ repl_chain_on_update(Slapi_PBlock *pb, Slapi_DN * target_dn,
}
}
- /* all other case (update while not directory manager) :
+ /* all other cases :
* or any normal non replicated client operation while local is disabled (import) :
* use the chaining backend
*/
diff --git a/ldap/servers/slapd/mapping_tree.c b/ldap/servers/slapd/mapping_tree.c
index 9336d7c..53df04a 100644
--- a/ldap/servers/slapd/mapping_tree.c
+++ b/ldap/servers/slapd/mapping_tree.c
@@ -47,7 +47,7 @@
/* distribution plugin prototype */
typedef int (* mtn_distrib_fct) (Slapi_PBlock *pb, Slapi_DN * target_dn,
- char **mtn_be_names, int be_count, Slapi_DN * mtn_node_dn, int *mtn_be_states);
+ char **mtn_be_names, int be_count, Slapi_DN * mtn_node_dn, int *mtn_be_states,
int rootmode);
struct mt_node
{
@@ -70,6 +70,7 @@ struct mt_node
* cn=config, cn=schema and root node */
char * mtn_dstr_plg_lib; /* distribution plugin library name */
char * mtn_dstr_plg_name; /* distribution plugin function name */
+ int mtn_dstr_plg_rootmode; /* determines how to process root updates in
distribution */
mtn_distrib_fct mtn_dstr_plg; /* pointer to the actual ditribution function
*/
void *mtn_extension; /* plugins can extend a mapping tree node */
};
@@ -302,7 +303,7 @@ mapping_tree_node_new(Slapi_DN *dn, Slapi_Backend **be, char
**backend_names, in
int count, int size,
char **referral, mapping_tree_node *parent,
int state, int private, char *plg_lib, char *plg_fct,
- mtn_distrib_fct plg)
+ mtn_distrib_fct plg, int plg_rootmode)
{
Slapi_RDN rdn;
mapping_tree_node *node;
@@ -326,6 +327,7 @@ mapping_tree_node_new(Slapi_DN *dn, Slapi_Backend **be, char
**backend_names, in
slapi_rdn_done(&rdn);
node->mtn_dstr_plg_lib = plg_lib;
node->mtn_dstr_plg_name = plg_fct;
+ node->mtn_dstr_plg_rootmode = plg_rootmode;
node->mtn_dstr_plg = plg;
slapi_log_error(SLAPI_LOG_TRACE, "mapping_tree",
@@ -621,6 +623,7 @@ mapping_tree_entry_add(Slapi_Entry *entry, mapping_tree_node
**newnodep )
int * be_states = NULL;
char * plugin_funct = NULL;
char * plugin_lib = NULL;
+ int plugin_rootmode = CHAIN_ROOT_UPDATE_REJECT;
mtn_distrib_fct plugin = NULL;
char **referral = NULL;
@@ -729,6 +732,24 @@ mapping_tree_entry_add(Slapi_Entry *entry, mapping_tree_node
**newnodep )
continue;
}
plugin_funct = slapi_ch_strdup(slapi_value_get_string(val));
+ } else if (!strcasecmp(type, "nsslapd-distribution-root-update")) {
+ const char *sval;
+ slapi_attr_first_value(attr, &val);
+ if (NULL == val) {
+ LDAPDebug(LDAP_DEBUG_ANY, "Warning: The nsslapd-distribution-plugin
attribute has no value for the mapping tree node %s\n",
+ slapi_entry_get_dn(entry), 0, 0);
+ continue;
+ }
+ sval = slapi_value_get_string(val);
+ if (strcmp(sval,"reject") == 0)
+ plugin_rootmode = CHAIN_ROOT_UPDATE_REJECT;
+ else if (strcmp(sval,"local") == 0)
+ plugin_rootmode = CHAIN_ROOT_UPDATE_LOCAL;
+ else if (strcmp(sval,"referral") == 0)
+ plugin_rootmode = CHAIN_ROOT_UPDATE_REFERRAL;
+ else
+ LDAPDebug(LDAP_DEBUG_ANY, "Warning: The
nsslapd-distribution-root-update attribute has undefined value (%s) for the mapping tree
node %s\n",
+ sval, slapi_entry_get_dn(entry), 0);
} else if (!strcasecmp(type, MAPPING_TREE_PARENT_ATTRIBUTE)) {
Slapi_DN *parent_node_dn = get_parent_from_entry(entry);
parent_node = mtn_get_mapping_tree_node_by_entry(
@@ -845,7 +866,7 @@ mapping_tree_entry_add(Slapi_Entry *entry, mapping_tree_node
**newnodep )
node= mapping_tree_node_new(subtree, be_list, be_names, be_states, be_list_count,
be_list_size, referral, parent_node, state,
0 /* Normal node. People can see and change it. */,
- plugin_lib, plugin_funct, plugin);
+ plugin_lib, plugin_funct, plugin, plugin_rootmode);
tmp_ndn = slapi_sdn_get_ndn( subtree );
if ( NULL != node && NULL == parent_node && tmp_ndn
@@ -1061,6 +1082,7 @@ int mapping_tree_entry_modify_callback(Slapi_PBlock *pb,
Slapi_Entry* entryBefor
int * be_states = NULL;
char * plugin_fct = NULL;
char * plugin_lib = NULL;
+ int plugin_rootmode = CHAIN_ROOT_UPDATE_REJECT;
int plugin_flag = 0;
mtn_distrib_fct plugin = NULL;
@@ -1325,6 +1347,38 @@ int mapping_tree_entry_modify_callback(Slapi_PBlock *pb,
Slapi_Entry* entryBefor
plugin_flag = 1;
}
+ else if (strcasecmp(mods[i]->mod_type,
+ "nsslapd-distribution-root-update" ) == 0)
+ {
+ if (SLAPI_IS_MOD_REPLACE(mods[i]->mod_op)
+ || SLAPI_IS_MOD_ADD(mods[i]->mod_op))
+ {
+ const char *sval;
+ slapi_entry_attr_find(entryAfter,
+ "nsslapd-distribution-root-update", &attr);
+ slapi_attr_first_value(attr, &val);
+ if (NULL == val) {
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "Warning: The nsslapd-distribution-root-update attribute"
+ " has no value for the mapping tree node %s\n",
+ slapi_entry_get_dn(entryAfter), 0, 0);
+ plugin_rootmode = CHAIN_ROOT_UPDATE_REJECT;
+ } else {
+ sval = slapi_value_get_string(val);
+ if (strcmp(sval,"reject") == 0)
+ plugin_rootmode = CHAIN_ROOT_UPDATE_REJECT;
+ else if (strcmp(sval,"local") == 0)
+ plugin_rootmode = CHAIN_ROOT_UPDATE_LOCAL;
+ else if (strcmp(sval,"referral") == 0)
+ plugin_rootmode = CHAIN_ROOT_UPDATE_REFERRAL;
+ }
+ }
+ else if (SLAPI_IS_MOD_DELETE(mods[i]->mod_op))
+ {
+ plugin_rootmode = CHAIN_ROOT_UPDATE_REJECT; /* default */
+ }
+ plugin_flag = 1;
+ }
}
/* if distribution plugin has been configured or modified
@@ -1371,6 +1425,7 @@ int mapping_tree_entry_modify_callback(Slapi_PBlock *pb,
Slapi_Entry* entryBefor
if (node->mtn_dstr_plg_name)
slapi_ch_free((void **) &node->mtn_dstr_plg_name);
node->mtn_dstr_plg_name = plugin_fct;
+ node->mtn_dstr_plg_rootmode = plugin_rootmode;
node->mtn_dstr_plg = plugin;
mtn_unlock();
}
@@ -1626,7 +1681,7 @@ add_internal_mapping_tree_node(const char *subtree, Slapi_Backend
*be, mapping_t
MTN_BACKEND,
1, /* The config node is a private node.
* People can't see or change it. */
- NULL, NULL, NULL);
+ NULL, NULL, NULL, 0); /* no distribution */
return node;
}
@@ -1994,6 +2049,8 @@ Slapi_Backend *slapi_mapping_tree_find_backend_for_sdn(Slapi_DN
*sdn)
}
operation_set_target_spec(op, sdn);
slapi_pblock_set(pb, SLAPI_OPERATION, op);
+ /* requestor dn is not set in pblock, so the distribution plugin
+ * will return index >= 0 */
index = mtn_get_be_distributed(pb, target_node, sdn, &flag_stop);
slapi_pblock_destroy(pb); /* also frees the operation */
@@ -2504,7 +2561,7 @@ mtn_get_be_distributed(Slapi_PBlock *pb, mapping_tree_node *
target_node,
{
index = (*target_node->mtn_dstr_plg)(pb, target_sdn,
target_node->mtn_backend_names, target_node->mtn_be_count,
- target_node->mtn_subtree, target_node->mtn_be_states);
+ target_node->mtn_subtree, target_node->mtn_be_states,
target_node->mtn_dstr_plg_rootmode);
if (index == SLAPI_BE_ALL_BACKENDS)
{
@@ -2513,6 +2570,12 @@ mtn_get_be_distributed(Slapi_PBlock *pb, mapping_tree_node *
target_node,
*/
index = 0;
}
+ /* check if distribution plugi returned a special mode for
+ * updates as root */
+ else if (index == -2 || index == -3)
+ {
+ /* nothing special to do */
+ }
/* paranoid check, never trust another programmer */
else if ((index >= target_node->mtn_be_count) || (index < 0))
{
@@ -2521,7 +2584,7 @@ mtn_get_be_distributed(Slapi_PBlock *pb, mapping_tree_node *
target_node,
" : %d for entry %s at node %s\n",
index, slapi_sdn_get_ndn(target_sdn),
slapi_sdn_get_ndn(target_node->mtn_subtree));
- index = 0;
+ index = 0;
}
else
{
@@ -2600,6 +2663,7 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock
*pb,
((SLAPI_OPERATION_SEARCH == op_type)||(SLAPI_OPERATION_BIND == op_type) ||
(SLAPI_OPERATION_UNBIND == op_type) || (SLAPI_OPERATION_COMPARE == op_type)))
||
override_referral) {
+ *referral = NULL;
if ((target_node == mapping_tree_root) ){
/* If we got here, then we couldn't find a matching node
* for the target. We'll use the default backend. Once
@@ -2622,11 +2686,18 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock
*pb,
} else {
*index = mtn_get_be_distributed(pb, target_node,
target_sdn, &flag_stop);
- }
- }
-
- if ((*index == -2) || (*index >= target_node->mtn_be_count)) {
- /* we have already returned all backends -> return NULL */
+ if (*index == -2)
+ result = LDAP_UNWILLING_TO_PERFORM;
+ }
+ }
+ if (*index == -3) {
+ *be = NULL;
+ *referral = (target_node->mtn_referral_entry ?
+ slapi_entry_dup(target_node->mtn_referral_entry) :
+ NULL);
+ (*index)++;
+ }else if ((*index == -2) || (*index >= target_node->mtn_be_count)) {
+ /* we have already returned all backends -> return NULL */
*be = NULL;
*referral = NULL;
} else {
@@ -2673,7 +2744,6 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock
*pb,
(*index)++;
}
}
- *referral = NULL;
} else {
/* otherwise we must return the referral
* if ((target_node->mtn_state == MTN_REFERRAL) ||
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
index 10d531e..900d3e5 100644
--- a/ldap/servers/slapd/slapi-private.h
+++ b/ldap/servers/slapd/slapi-private.h
@@ -762,6 +762,9 @@ char * slapi_schema_get_superior_name(const char *ocname_or_oid);
CSN *dup_global_schema_csn();
/* misc function for the chaining backend */
+#define CHAIN_ROOT_UPDATE_REJECT 0
+#define CHAIN_ROOT_UPDATE_LOCAL 1
+#define CHAIN_ROOT_UPDATE_REFERRAL 2
char * slapi_get_rootdn(); /* return the directory manager dn in use */
/* plugin interface to bulk import */