ldap/servers
by Mark Reynolds
ldap/servers/slapd/configdse.c | 38 +++++++++++++++++++++++++++++++++++---
1 file changed, 35 insertions(+), 3 deletions(-)
New commits:
commit 72b7e914195cf9c65aa1f635d786859d8b578aaf
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Fri May 25 16:41:22 2012 -0400
Ticket #28 - MOD operations with chained delete/add get back error 53 on backend config
Bug Description: If you try and delete/add a config attribute, an error 53 is returned.
Fix Description: Allow a delete of a config attribute if we add it back in the same mod set.
https://fedorahosted.org/389/ticket/28
Reviewed by: Noriko (Thanks!)
diff --git a/ldap/servers/slapd/configdse.c b/ldap/servers/slapd/configdse.c
index 12175c4..51f9165 100644
--- a/ldap/servers/slapd/configdse.c
+++ b/ldap/servers/slapd/configdse.c
@@ -55,6 +55,7 @@
#include "pw.h"
static int check_all_maxdiskspace_and_mlogsize(Slapi_PBlock *pb, LDAPMod **mod, char *returntext);
+static int is_delete_a_replace(LDAPMod **mods, int mod_count);
static void get_log_max_size( LDAPMod *mod,
char *maxdiskspace_str,
char *mlogsize_str,
@@ -423,9 +424,17 @@ modify_config_dse(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, in
config_attr);
}
} else {
- rc= LDAP_UNWILLING_TO_PERFORM;
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Deleting attributes is not allowed");
+ /*
+ * Check if this delete is followed by an add of the same attribute, as some
+ * clients do a replace by deleting and adding the attribute.
+ */
+ if(is_delete_a_replace(mods, i)){
+ rc = config_set(config_attr, mods[i]->mod_bvalues, returntext, apply_mods);
+ } else {
+ rc= LDAP_UNWILLING_TO_PERFORM;
+ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
+ "Deleting attributes is not allowed");
+ }
}
} else if (SLAPI_IS_MOD_REPLACE(mods[i]->mod_op)) {
if (( checked_all_maxdiskspace_and_mlogsize == 0 ) &&
@@ -600,3 +609,26 @@ get_log_max_size( LDAPMod *mod,
*mlogsize = atoi((char *) mod->mod_bvalues[0]->bv_val);
}
}
+
+/*
+ * Loops through all the mods, if we add the attribute back, it's a replace, but we need
+ * to keep looking through the mods in case it gets deleted again.
+ */
+static int
+is_delete_a_replace(LDAPMod **mods, int mod_count){
+ char *del_attr = mods[mod_count]->mod_type;
+ int rc = 0;
+ int i;
+
+ for(i = mod_count + 1; mods[i] != NULL; i++){
+ if(strcasecmp(mods[i]->mod_type, del_attr) == 0 && SLAPI_IS_MOD_ADD(mods[i]->mod_op)){
+ /* ok, we are adding this attribute back */
+ rc = 1;
+ } else if(strcasecmp(mods[i]->mod_type, del_attr) == 0 && SLAPI_IS_MOD_DELETE(mods[i]->mod_op)){
+ /* whoops we deleted it again */
+ rc = 0;
+ }
+ }
+
+ return rc;
+}
11 years, 6 months
ldap/servers
by Mark Reynolds
ldap/servers/plugins/replication/repl5.h | 10
ldap/servers/plugins/replication/repl5_connection.c | 26 +
ldap/servers/plugins/replication/repl5_replica_config.c | 257 +++++++++++++---
ldap/servers/plugins/replication/repl_extop.c | 91 +++--
4 files changed, 316 insertions(+), 68 deletions(-)
New commits:
commit 507b593fa47efeb8a4fc3c2d6b75428e7a69a480
Author: Mark Reynolds <mareynol(a)redhat.com>
Date: Wed May 16 11:28:01 2012 -0400
Ticket 368 - Make the cleanAllRUV task one step
Bug Description: The first version of this fix required a second releaseRUV step.
Fix Description: Created a new "monitoring" thread that checks all the replicas RUV's
to see if the rid was cleaned. Once they are cleaned, we automatically
release the RID for reuse.
I also refined the logging so it easy to track the status of the task.
https://fedorahosted.org/389/ticket/368
reviewed by: richm (Thanks Rich!)
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index d3feeb0..b04d9c4 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -439,6 +439,9 @@ long conn_get_timeout(Repl_Connection *conn);
void conn_set_agmt_changed(Repl_Connection *conn);
ConnResult conn_read_result(Repl_Connection *conn, int *message_id);
ConnResult conn_read_result_ex(Repl_Connection *conn, char **retoidp, struct berval **retdatap, LDAPControl ***returned_controls, int send_msgid, int *resp_msgid, int noblock);
+LDAP * conn_get_ldap(Repl_Connection *conn);
+void conn_lock(Repl_Connection *conn);
+void conn_unlock(Repl_Connection *conn);
/* In repl5_protocol.c */
typedef struct repl_protocol Repl_Protocol;
@@ -598,9 +601,16 @@ void set_released_rid(int rid);
int is_released_rid(int rid);
int is_already_released_rid();
void delete_released_rid();
+void replica_cleanallruv_monitor_thread(void *arg);
#define ALREADY_RELEASED -1
+typedef struct _cleanruv_data
+{
+ Object *repl_obj;
+ ReplicaId rid;
+} cleanruv_data;
+
/* replutil.c */
LDAPControl* create_managedsait_control ();
LDAPControl* create_backend_control(Slapi_DN *sdn);
diff --git a/ldap/servers/plugins/replication/repl5_connection.c b/ldap/servers/plugins/replication/repl5_connection.c
index a074a9f..5fdc601 100644
--- a/ldap/servers/plugins/replication/repl5_connection.c
+++ b/ldap/servers/plugins/replication/repl5_connection.c
@@ -1710,6 +1710,16 @@ conn_get_timeout(Repl_Connection *conn)
return retval;
}
+LDAP *
+conn_get_ldap(Repl_Connection *conn)
+{
+ if(conn){
+ return conn->ld;
+ } else {
+ return NULL;
+ }
+}
+
void conn_set_agmt_changed(Repl_Connection *conn)
{
PR_ASSERT(NULL != conn);
@@ -1908,3 +1918,19 @@ repl5_debug_timeout_callback(time_t when, void *arg)
"repl5_debug_timeout_callback: set debug level to %d at %ld\n",
s_debug_level, when);
}
+
+void
+conn_lock(Repl_Connection *conn)
+{
+ if(conn){
+ PR_Lock(conn->lock);
+ }
+}
+
+void
+conn_unlock(Repl_Connection *conn)
+{
+ if(conn){
+ PR_Unlock(conn->lock);
+ }
+}
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index 5a3ed07..ca646e9 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -81,12 +81,12 @@ static int replica_execute_cl2ldif_task (Object *r, char *returntext);
static int replica_execute_ldif2cl_task (Object *r, char *returntext);
static int replica_execute_cleanruv_task (Object *r, ReplicaId rid, char *returntext);
static int replica_execute_cleanall_ruv_task (Object *r, ReplicaId rid, char *returntext);
-static int replica_execute_release_ruv_task(Object *r, ReplicaId rid, char *returntext);
+static int replica_execute_release_ruv_task(Object *r, ReplicaId rid);
static struct berval *create_ruv_payload(char *value);
static int replica_cleanup_task (Object *r, const char *task_name, char *returntext, int apply_mods);
static int replica_task_done(Replica *replica);
-
static multimaster_mtnode_extension * _replica_config_get_mtnode_ext (const Slapi_Entry *e);
+int g_get_shutdown();
/*
* Note: internal add/modify/delete operations should not be run while
@@ -860,21 +860,6 @@ static int replica_execute_task (Object *r, const char *task_name, char *returnt
else
return LDAP_SUCCESS;
}
- else if (strncasecmp (task_name, RELEASERUV, RELEASERUVLEN) == 0)
- {
- int temprid = atoi(&(task_name[RELEASERUVLEN]));
- if (temprid <= 0 || temprid >= READ_ONLY_REPLICA_ID){
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Invalid replica id for task - %s", task_name);
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,"replica_execute_task: %s\n", returntext);
- return LDAP_OPERATIONS_ERROR;
- }
- if (apply_mods)
- {
- return replica_execute_release_ruv_task(r, (ReplicaId)temprid, returntext);
- }
- else
- return LDAP_SUCCESS;
- }
else
{
PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "unsupported replica task - %s", task_name);
@@ -1177,7 +1162,6 @@ replica_execute_cleanruv_task (Object *r, ReplicaId rid, char *returntext /* not
* Clean the changelog RUV's, and set the rids
*/
cl5CleanRUV(rid);
- set_cleaned_rid(rid);
delete_released_rid();
if (rc != RUV_SUCCESS){
@@ -1191,19 +1175,22 @@ replica_execute_cleanruv_task (Object *r, ReplicaId rid, char *returntext /* not
static int
replica_execute_cleanall_ruv_task (Object *r, ReplicaId rid, char *returntext)
{
+ PRThread *thread = NULL;
Repl_Connection *conn;
Replica *replica = (Replica*)object_get_data (r);
Object *agmt_obj;
Repl_Agmt *agmt;
ConnResult crc;
+ cleanruv_data *data = NULL;
const Slapi_DN *dn = NULL;
struct berval *payload = NULL;
char *ridstr = NULL;
int send_msgid = 0;
+ int agmt_count = 0;
int rc = 0;
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanAllRUV_task: cleaning rid (%d)...\n",(int)rid);
-
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: cleaning rid (%d)...\n",(int)rid);
+ set_cleaned_rid(rid);
/*
* Create payload
*/
@@ -1245,8 +1232,9 @@ replica_execute_cleanall_ruv_task (Object *r, ReplicaId rid, char *returntext)
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: failed to send "
"cleanruv extended op to repl agmt (%s), error %d\n", slapi_sdn_get_dn(dn), crc);
} else {
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanAllRUV_task: successfully sent "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: successfully sent "
"cleanruv extended op to (%s)\n",slapi_sdn_get_dn(dn));
+ agmt_count++;
}
conn_start_linger(conn);
}
@@ -1270,17 +1258,218 @@ done:
*/
replica_execute_cleanruv_task (r, rid, returntext);
- if(rc == 0){
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanAllRUV_task: operation successful\n");
+ if(rc == 0 && agmt_count > 0){ /* success, but we need to check our replicas */
+ /*
+ * Launch the cleanruv monitoring thread. Once all the replicas are cleaned it will release the rid
+ */
+ data = (cleanruv_data*)slapi_ch_calloc(1, sizeof(cleanruv_data));
+ if (data == NULL) {
+ slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: failed to allocate "
+ "cleanruv_data. Aborting task.\n");
+ return -1;
+ }
+ data->repl_obj = r;
+ data->rid = rid;
+
+ thread = PR_CreateThread(PR_USER_THREAD, replica_cleanallruv_monitor_thread,
+ (void *)data, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
+ if (thread == NULL) {
+ slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: unable to create cleanAllRUV "
+ "monitoring thread. Aborting task.\n");
+ }
+
+ } else if(r == 0){ /* success */
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: Successfully Finished.\n");
} else {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: operation failed (%d)\n",rc);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: Task failed (%d)\n",rc);
}
return rc;
}
+/*
+ * After all the cleanAllRUV extended ops have been sent, we need to monitoring those replicas'
+ * RUVs. Once the rid is cleaned, then we need to release it, and push this "release"
+ * to the other replicas
+ */
+void
+replica_cleanallruv_monitor_thread(void *arg)
+{
+ Object *agmt_obj;
+ LDAP *ld;
+ Repl_Connection *conn;
+ Repl_Agmt *agmt;
+ Replica *replica;;
+ cleanruv_data *data = arg;
+ LDAPMessage *result, *entry;
+ BerElement *ber;
+ time_t start_time;
+ struct berval **vals;
+ char *rid_text;
+ char *attrs[2];
+ char *attr;
+ int replicas_cleaned = 0;
+ int found = 0;
+ int crc;
+ int rc = 0;
+ int i;
+
+ /*
+ * Initialize our settings
+ */
+ attrs[0] = "nsds50ruv";
+ attrs[1] = NULL;
+ rid_text = slapi_ch_smprintf("{replica %d ldap", data->rid);
+ replica = (Replica*)object_get_data (data->repl_obj);
+ start_time = current_time();
+
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: Waiting for all the replicas to get cleaned...\n");
+
+ while(!g_get_shutdown())
+ {
+ DS_Sleep(PR_SecondsToInterval(10));
+ found = 0;
+ agmt_obj = agmtlist_get_first_agreement_for_replica (replica);
+ while (agmt_obj){
+ agmt = (Repl_Agmt*)object_get_data (agmt_obj);
+ if(!agmt_is_enabled(agmt)){
+ agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj);
+ continue;
+ }
+ /*
+ * Get the replication connection
+ */
+ conn = (Repl_Connection *)agmt_get_connection(agmt);
+ crc = conn_connect(conn);
+ if (CONN_OPERATION_FAILED == crc ){
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: monitor thread failed to connect "
+ "to repl agreement connection (%s), error %d\n","", ACQUIRE_TRANSIENT_ERROR);
+ continue;
+ } else if (CONN_SSL_NOT_ENABLED == crc){
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: monitor thread failed to acquire "
+ "repl agmt connection (%s), error %d\n","", ACQUIRE_FATAL_ERROR);
+ continue;
+ }
+ /*
+ * Get the LDAP connection handle from the conn
+ */
+ ld = conn_get_ldap(conn);
+ if(ld == NULL){
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: monitor thread failed to get LDAP "
+ "handle from the replication agmt (%s). Moving on to the next agmt.\n",agmt_get_long_name(agmt));
+ continue;
+ }
+ /*
+ * Search this replica for its tombstone/ruv entry
+ */
+ conn_cancel_linger(conn);
+ conn_lock(conn);
+ rc = ldap_search_ext_s(ld, slapi_sdn_get_dn(agmt_get_replarea(agmt)), LDAP_SCOPE_SUBTREE,
+ "(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectclass=nstombstone))",
+ attrs, 0, NULL, NULL, NULL, 0, &result);
+ if(rc != LDAP_SUCCESS){
+ /*
+ * Couldn't contact ldap server, what should we do?
+ *
+ * Skip it and move on! It's the admin's job to make sure all the replicas are up and running
+ */
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: monitor thread failed to contact "
+ "agmt (%s), moving on to the next agmt.\n", agmt_get_long_name(agmt));
+ conn_unlock(conn);
+ conn_start_linger(conn);
+ continue;
+ }
+ /*
+ * There is only one entry. Check its "nsds50ruv" for our cleaned rid
+ */
+ entry = ldap_first_entry( ld, result );
+ if ( entry != NULL ) {
+ for ( attr = ldap_first_attribute( ld, entry, &ber ); attr != NULL; attr = ldap_next_attribute( ld, entry, ber ) ){
+ /* make sure the attribute is nsds50ruv */
+ if(strcasecmp(attr,"nsds50ruv") != 0){
+ continue;
+ }
+ if ((vals = ldap_get_values_len( ld, entry, attr)) != NULL ) {
+ for ( i = 0; vals[i] && vals[i]->bv_val; i++ ) {
+ /* look for this replica */
+ if(strstr(rid_text, vals[i]->bv_val)){
+ /* rid has not been cleaned yet, start over */
+ found = 1;
+ break;
+ }
+ }
+ ldap_value_free_len(vals);
+ }
+ ldap_memfree( attr );
+ }
+ if ( ber != NULL ) {
+ ber_free( ber, 0 );
+ }
+ }
+ ldap_msgfree( result );
+ /*
+ * Unlock the connection, and start the linger timer
+ */
+ conn_unlock(conn);
+ conn_start_linger(conn);
+
+ if(found){
+ /*
+ * If we've been trying to clean these replicas for over an hour, just quit
+ */
+ if( (current_time() - start_time) > 3600){
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: timed out checking if replicas have "
+ "been cleaned. The rid has not been released, you need to rerun the task.\n");
+ goto done;
+ }
+ /*
+ * a rid has not been cleaned yet, go back to sleep and check them again
+ */
+ break;
+ }
+
+ agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj);
+ }
+ if(!found){
+ /*
+ * The replicas have been cleaned! Next, release the rid
+ */
+ replicas_cleaned = 1;
+ break;
+ }
+ } /* while */
+
+ /*
+ * If the replicas are cleaned, release the rid
+ */
+ if(replicas_cleaned){
+ rc = replica_execute_release_ruv_task(data->repl_obj, data->rid);
+ if(rc == 0){
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: Successfully Finished. All active "
+ "replicas have been cleaned.\n");
+ } else {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: Failed: Replica ID was not released (%d) "
+ "You will need to rerun the task.\n", rc);
+ }
+ } else {
+ /*
+ * Shutdown
+ */
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: slapd shutting down, you will need to rerun the task.\n");
+ }
+
+done:
+ slapi_ch_free((void **)&rid_text);
+ slapi_ch_free((void **)&data);
+}
+
+/*
+ * This function releases the cleaned rid so that it can be reused.
+ * We send this operation to all the known active replicas.
+ */
static int
-replica_execute_release_ruv_task(Object *r, ReplicaId rid, char *returntext)
+replica_execute_release_ruv_task(Object *r, ReplicaId rid)
{
Repl_Connection *conn;
Replica *replica = (Replica*)object_get_data (r);
@@ -1293,7 +1482,7 @@ replica_execute_release_ruv_task(Object *r, ReplicaId rid, char *returntext)
int send_msgid = 0;
int rc = 0;
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "releaseRUV_task: releasing rid (%d)...\n", rid);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: releasing rid (%d)...\n", rid);
/*
* Set the released rid, and trigger cl trimmming
@@ -1339,18 +1528,18 @@ replica_execute_release_ruv_task(Object *r, ReplicaId rid, char *returntext)
conn_cancel_linger(conn);
crc = conn_send_extended_operation(conn, REPL_RELEASERUV_OID, payload, NULL, &send_msgid);
if (CONN_OPERATION_SUCCESS != crc){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseRUV_task: failed to send "
- "releaseruv extended op to repl agmt (%s), error %d\n", slapi_sdn_get_dn(dn), crc);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: failed to send "
+ "releaseRUV extended op to repl agmt (%s), error %d\n", slapi_sdn_get_dn(dn), crc);
rc = LDAP_OPERATIONS_ERROR;
} else {
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "releaseRUV_task: successfully sent "
- "extended op to (%s)\n",slapi_sdn_get_dn(dn));
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: successfully sent "
+ "releaseRUV extended op to (%s)\n",slapi_sdn_get_dn(dn));
}
conn_start_linger(conn);
}
if(crc){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseRUV_task: replica (%s) has not "
- "been cleaned. You will need to rerun the RELEASERUV task on this replica\n",
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: replica (%s) has not "
+ "been released. You will need to rerun the task\n",
slapi_sdn_get_dn(dn));
rc = crc;
}
@@ -1364,9 +1553,9 @@ done:
if(rc == 0){
set_released_rid(ALREADY_RELEASED);
delete_cleaned_rid();
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "releaseRUV_task: Successfully released rid (%d)\n", rid);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: Successfully released rid (%d)\n", rid);
} else {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseRUV_task: Failed to release rid (%d), error (%d)\n", rid, rc);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: Failed to release rid (%d), error (%d)\n", rid, rc);
}
if(payload)
diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c
index e4abde0..f6378d2 100644
--- a/ldap/servers/plugins/replication/repl_extop.c
+++ b/ldap/servers/plugins/replication/repl_extop.c
@@ -1388,18 +1388,21 @@ free_and_return:
int
multimaster_extop_cleanruv(Slapi_PBlock *pb){
multimaster_mtnode_extension *mtnode_ext;
+ PRThread *thread = NULL;
Repl_Connection *conn;
const Slapi_DN *dn;
Replica *r = NULL;
Object *agmt_obj;
Repl_Agmt *agmt;
ConnResult crc;
+ cleanruv_data *data = NULL;
struct berval *extop_value;
char *extop_oid;
char *repl_root;
char *payload = NULL;
char *iter;
int send_msgid = 0;
+ int agmt_count = 0;
int rid = 0;
int rc = 0;
@@ -1411,41 +1414,39 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb){
/* something is wrong, error out */
return -1;
}
-
/*
* Extract the rid and repl_root from the payload
*/
if(decode_cleanruv_payload(extop_value, &payload)){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanruv_extop: failed to decode payload. Aborting ext op\n");
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: failed to decode payload. Aborting ext op\n");
return -1;
}
rid = atoi(ldap_utf8strtok_r(payload, ":", &iter));
repl_root = ldap_utf8strtok_r(iter, ":", &iter);
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanruv_extop: cleaning rid (%d)...\n",rid);
-
/*
* If we already cleaned this server, just return success
*/
if(is_cleaned_rid(rid)){
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanruv_extop: rid (%d) has already been cleaned, skipping\n",rid);
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanAllRUV_extop: rid (%d) has already been cleaned, skipping\n",rid);
return rc;
} else {
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanruv_extop: cleaning rid (%d)...\n", rid);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: cleaning rid (%d)...\n", rid);
+ set_cleaned_rid(rid);
}
/*
* Get the node, so we can get the replica and its agreements
*/
if((mtnode_ext = replica_config_get_mtnode_by_dn(repl_root)) == NULL){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanruv_extop: failed to get replication node "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: failed to get replication node "
"from (%s), aborting operation\n", repl_root);
return -1;
}
if (mtnode_ext->replica)
object_acquire (mtnode_ext->replica);
if (mtnode_ext->replica == NULL){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanruv_extop: replica is missing from (%s), "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: replica is missing from (%s), "
"aborting operation\n",repl_root);
rc = LDAP_OPERATIONS_ERROR;
goto free_and_return;
@@ -1466,36 +1467,37 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb){
conn = (Repl_Connection *)agmt_get_connection(agmt);
if(conn == NULL){
/* no connection for this agreement, move on to the next agmt */
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanruv_extop: the replica (%s), is "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: the replica (%s), is "
"missing the connection. This replica will not be cleaned.\n", slapi_sdn_get_dn(dn));
agmt_obj = agmtlist_get_next_agreement_for_replica (r, agmt_obj);
continue;
}
crc = conn_connect(conn);
if (CONN_OPERATION_FAILED == crc ){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanruv_extop: failed to connect "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: failed to connect "
"to repl agreement connection (%s), error %d\n",slapi_sdn_get_dn(dn), ACQUIRE_TRANSIENT_ERROR);
rc = LDAP_OPERATIONS_ERROR;
} else if (CONN_SSL_NOT_ENABLED == crc){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanruv_extop: failed to acquire "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: failed to acquire "
"repl agmt connection (%s), error %d\n",slapi_sdn_get_dn(dn), ACQUIRE_FATAL_ERROR);
rc = LDAP_OPERATIONS_ERROR;
} else {
conn_cancel_linger(conn);
crc = conn_send_extended_operation(conn, REPL_CLEANRUV_OID, extop_value, NULL, &send_msgid);
if (CONN_OPERATION_SUCCESS != crc){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanruv_extop: failed to send "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: failed to send "
"clean_ruv extended op to repl agmt (%s), error %d\n", slapi_sdn_get_dn(dn), crc);
rc = LDAP_OPERATIONS_ERROR;
} else {
/* success */
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanruv_extop: successfully sent "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: successfully sent "
"extended op to (%s)\n",slapi_sdn_get_dn(dn) );
+ agmt_count++;
}
conn_start_linger(conn);
}
if(crc != CONN_OPERATION_SUCCESS){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanruv_extop: replica (%s) has not "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: replica (%s) has not "
"been cleaned. You will need to rerun the CLEANALLRUV task on this replica\n",
slapi_sdn_get_dn(dn) );
rc = LDAP_OPERATIONS_ERROR;
@@ -1508,10 +1510,30 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb){
free_and_return:
- if(rc == 0){
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanruv_extop: cleaned rid (%d)\n", rid);
+ if(rc == 0 && agmt_count > 0){
+ /*
+ * Launch the cleanruv monitoring thread. Once all the replicas are cleaned it will release the rid
+ */
+ data = (cleanruv_data*)slapi_ch_calloc(1, sizeof(cleanruv_data));
+ if (data == NULL) {
+ slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: failed to allocate "
+ "cleanruv_Data\n");
+ return -1;
+ }
+ data->repl_obj = mtnode_ext->replica;
+ data->rid = rid;
+
+ thread = PR_CreateThread(PR_USER_THREAD, replica_cleanallruv_monitor_thread,
+ (void *)data, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
+ if (thread == NULL) {
+ slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: unable to create cleanAllRUV "
+ "monitoring thread. Aborting task.\n");
+ }
+ } else if (rc == 0){
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: Successfully Finished.\n");
} else {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanruv_extop: failed to clean rid (%d), error (%d)\n",rid, rc);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanALLRUV_extop: failed to clean rid (%d), error (%d)\n",rid, rc);
}
if (mtnode_ext->replica)
@@ -1558,34 +1580,34 @@ multimaster_extop_releaseruv(Slapi_PBlock *pb){
}
if(decode_cleanruv_payload(extop_value, &payload)){
- slapi_log_error(SLAPI_LOG_FATAL,repl_plugin_name, "releaseruv_extop: failed to decode payload, aborting ext op\n");
+ slapi_log_error(SLAPI_LOG_FATAL,repl_plugin_name, "releaseRUV_extop: failed to decode payload, aborting ext op.\n");
return -1;
}
rid = atoi(ldap_utf8strtok_r(payload, ":", &iter));
repl_root = ldap_utf8strtok_r(iter, ":", &iter);
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "releaseruv_extop: releasing rid (%d)...\n",rid);
/*
* If we already released this ruv, just return.
*/
if(is_released_rid(rid) || is_already_released_rid()){
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "releaseruv_extop: rid (%d) has already been released, skipping\n",rid);
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanAllRUV_extop: rid (%d) has already been released, skipping.\n",rid);
return 0;
} else {
/* set the released rid, and trigger trimming */
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: releasing rid (%d)...\n", rid);
set_released_rid((int)rid);
trigger_cl_trimming();
}
if((mtnode_ext = replica_config_get_mtnode_by_dn(repl_root)) == NULL){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseruv_extop: failed to get node "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseRUV_extop: failed to get node "
"from replication root dn(%s), aborting operation.\n", repl_root);
return -1;
}
if (mtnode_ext->replica)
object_acquire (mtnode_ext->replica);
if (mtnode_ext->replica == NULL){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseruv_extop: replica is missing from (%s), "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseRUV_extop: replica is missing from (%s), "
"aborting operation.\n", repl_root);
rc = LDAP_OPERATIONS_ERROR;
goto free_and_return;
@@ -1606,38 +1628,38 @@ multimaster_extop_releaseruv(Slapi_PBlock *pb){
conn = (Repl_Connection *)agmt_get_connection(agmt);
if(conn == NULL){
/* no connection for this agreement, log error, and move on */
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseruv_extop: the replica (%s), is "
- "missing the connection. This replica will not be cleaned.\n", slapi_sdn_get_dn(dn));
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: the replica (%s), is "
+ "missing the connection. This replica will not be released.\n", slapi_sdn_get_dn(dn));
agmt_obj = agmtlist_get_next_agreement_for_replica (r, agmt_obj);
continue;
}
crc = conn_connect(conn);
if (CONN_OPERATION_FAILED == crc ){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseruv_extop: failed to connect "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseRUV_extop: failed to connect "
"to repl agreement connection (%s), error %d\n",slapi_sdn_get_dn(dn), ACQUIRE_TRANSIENT_ERROR);
rc = LDAP_OPERATIONS_ERROR;
} else if (CONN_SSL_NOT_ENABLED == crc){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseruv_extop: failed to acquire "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseRUV_extop: failed to acquire "
"repl agmt connection (%s), error %d\n",slapi_sdn_get_dn(dn), ACQUIRE_FATAL_ERROR);
rc = LDAP_OPERATIONS_ERROR;
} else {
conn_cancel_linger(conn);
crc = conn_send_extended_operation(conn, REPL_RELEASERUV_OID, extop_value, NULL, &send_msgid);
if (CONN_OPERATION_SUCCESS != crc){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseruv_extop: failed to send "
- "releaseruv extended op to repl agmt (%s), error %d\n", slapi_sdn_get_dn(dn), crc);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: failed to send "
+ "releaseRUV extended op to repl agmt (%s), error %d\n", slapi_sdn_get_dn(dn), crc);
rc = LDAP_OPERATIONS_ERROR;
} else {
/* success */
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "releaseruv_extop: successfully sent "
- "extended op to (%s)\n",slapi_sdn_get_dn(dn) );
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: successfully sent "
+ "releaseRUV extended op to (%s)\n",slapi_sdn_get_dn(dn) );
rc = 0;
}
conn_start_linger(conn);
}
if(crc){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseruv_extop: replica (%s) has not "
- "been cleaned. You will need to rerun the RELEASERUV task on this replica\n",
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: replica (%s) has not "
+ "been released. You will need to rerun the task.\n",
slapi_sdn_get_dn(dn) );
}
agmt_obj = agmtlist_get_next_agreement_for_replica (r, agmt_obj);
@@ -1650,9 +1672,10 @@ free_and_return:
if(rc == 0){
set_released_rid(ALREADY_RELEASED);
delete_cleaned_rid();
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "releaseruv_extop: released rid (%d) successfully\n", rid);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: Successfully released rid (%d)\n", rid);
} else {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseruv_extop: failed to release rid(%d), error (%d), please retry the task\n",rid, rc);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: Failed to release rid(%d), error (%d), "
+ "please retry the task.\n",rid, rc);
}
if(mtnode_ext->replica)
11 years, 6 months
ldap/ldif ldap/servers Makefile.am Makefile.in
by Mark Reynolds
Makefile.am | 13
Makefile.in | 50 +
ldap/ldif/template-dse.ldif.in | 11
ldap/servers/plugins/rootdn_access/rootdn_access.c | 663 +++++++++++++++++++++
ldap/servers/plugins/rootdn_access/rootdn_access.h | 57 +
ldap/servers/slapd/bind.c | 34 -
ldap/servers/slapd/pblock.c | 14
ldap/servers/slapd/plugin.c | 11
ldap/servers/slapd/slap.h | 2
ldap/servers/slapd/slapi-plugin.h | 3
10 files changed, 846 insertions(+), 12 deletions(-)
New commits:
commit c61ee8e16c3e3ca91ffef725fadbeb0a62fb5e80
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Fri May 25 12:26:02 2012 -0400
Ticket #110 - RFE limiting root DN by host, IP, time of day, day of week
RFE Description: There is no way to restrict when and where some one can attempt
root DN binds. An intruder can brute force guess the password all
day long until they succeed, especailly if the DS is publicly
available.
Fix Description: Created a new plugin, type "internalpreoperation" and an internal
preop bind function. You can configure the plugin with some basic
access control:
rootdn-open-time: 0800
rootdn-close-time: 1700
rootdn-days-allowed: Mon, Tue, Wed, Thu, Fri
rootdn-allow-host: *.redhat.com
rootdn-allow-host: *.fedora.com
rootdn-deny-host: dangerous.boracle.com
rootdn-allow-ip: 127.0.0.1
rootdn-allow-ip: 2000:db8:de30::11
rootdn-deny-ip: 192.168.1.*
As with our other ACL code, deny's always override the allow rules.
https://fedorahosted.org/389/ticket/110
Reviewed by: richm(Thanks Rich!)
diff --git a/Makefile.am b/Makefile.am
index cf91842..d90cd4b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -205,7 +205,7 @@ serverplugin_LTLIBRARIES = libacl-plugin.la libattr-unique-plugin.la \
libreferint-plugin.la libreplication-plugin.la libretrocl-plugin.la \
libroles-plugin.la libstatechange-plugin.la libsyntax-plugin.la \
libviews-plugin.la libschemareload-plugin.la libusn-plugin.la \
- libacctusability-plugin.la $(LIBACCTPOLICY_PLUGIN) \
+ libacctusability-plugin.la librootdn-access-plugin.la $(LIBACCTPOLICY_PLUGIN) \
$(LIBPAM_PASSTHRU_PLUGIN) $(LIBDNA_PLUGIN) \
$(LIBBITWISE_PLUGIN) $(LIBPRESENCE_PLUGIN)
@@ -822,6 +822,17 @@ libacl_plugin_la_LDFLAGS = -avoid-version
libacl_plugin_la_LINK = $(CXXLINK) -avoid-version
#------------------------
+# librootdn-access-plugin
+#------------------------
+#
+librootdn_access_plugin_la_SOURCES = ldap/servers/plugins/rootdn_access/rootdn_access.c
+
+librootdn_access_plugin_la_CPPFLAGS = $(PLUGIN_CPPFLAGS)
+librootdn_access_plugin_la_LIBADD = libslapd.la $(NSPR_LINK)
+librootdn_access_plugin_la_LDFLAGS = -avoid-version
+
+
+#------------------------
# libautomember-plugin
#------------------------
libautomember_plugin_la_SOURCES = ldap/servers/plugins/automember/automember.c
diff --git a/Makefile.in b/Makefile.in
index ab2f657..915e978 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -581,6 +581,15 @@ libroles_plugin_la_OBJECTS = $(am_libroles_plugin_la_OBJECTS)
libroles_plugin_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libroles_plugin_la_LDFLAGS) $(LDFLAGS) -o $@
+librootdn_access_plugin_la_DEPENDENCIES = libslapd.la \
+ $(am__DEPENDENCIES_1)
+am_librootdn_access_plugin_la_OBJECTS = ldap/servers/plugins/rootdn_access/librootdn_access_plugin_la-rootdn_access.lo
+librootdn_access_plugin_la_OBJECTS = \
+ $(am_librootdn_access_plugin_la_OBJECTS)
+librootdn_access_plugin_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(librootdn_access_plugin_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
libschemareload_plugin_la_DEPENDENCIES = libslapd.la \
$(am__DEPENDENCIES_1)
am_libschemareload_plugin_la_OBJECTS = ldap/servers/plugins/schema_reload/libschemareload_plugin_la-schema_reload.lo
@@ -1001,6 +1010,7 @@ SOURCES = $(libavl_a_SOURCES) $(libldaputil_a_SOURCES) \
$(libreferint_plugin_la_SOURCES) \
$(libreplication_plugin_la_SOURCES) \
$(libretrocl_plugin_la_SOURCES) $(libroles_plugin_la_SOURCES) \
+ $(librootdn_access_plugin_la_SOURCES) \
$(libschemareload_plugin_la_SOURCES) $(libslapd_la_SOURCES) \
$(libstatechange_plugin_la_SOURCES) \
$(libsyntax_plugin_la_SOURCES) $(libusn_plugin_la_SOURCES) \
@@ -1033,6 +1043,7 @@ DIST_SOURCES = $(libavl_a_SOURCES) $(libldaputil_a_SOURCES) \
$(libreferint_plugin_la_SOURCES) \
$(libreplication_plugin_la_SOURCES) \
$(libretrocl_plugin_la_SOURCES) $(libroles_plugin_la_SOURCES) \
+ $(librootdn_access_plugin_la_SOURCES) \
$(libschemareload_plugin_la_SOURCES) \
$(am__libslapd_la_SOURCES_DIST) \
$(libstatechange_plugin_la_SOURCES) \
@@ -1411,7 +1422,7 @@ serverplugin_LTLIBRARIES = libacl-plugin.la libattr-unique-plugin.la \
libreferint-plugin.la libreplication-plugin.la libretrocl-plugin.la \
libroles-plugin.la libstatechange-plugin.la libsyntax-plugin.la \
libviews-plugin.la libschemareload-plugin.la libusn-plugin.la \
- libacctusability-plugin.la $(LIBACCTPOLICY_PLUGIN) \
+ libacctusability-plugin.la librootdn-access-plugin.la $(LIBACCTPOLICY_PLUGIN) \
$(LIBPAM_PASSTHRU_PLUGIN) $(LIBDNA_PLUGIN) \
$(LIBBITWISE_PLUGIN) $(LIBPRESENCE_PLUGIN)
@@ -1968,6 +1979,15 @@ libacl_plugin_la_LDFLAGS = -avoid-version
libacl_plugin_la_LINK = $(CXXLINK) -avoid-version
#------------------------
+# librootdn-access-plugin
+#------------------------
+#
+librootdn_access_plugin_la_SOURCES = ldap/servers/plugins/rootdn_access/rootdn_access.c
+librootdn_access_plugin_la_CPPFLAGS = $(PLUGIN_CPPFLAGS)
+librootdn_access_plugin_la_LIBADD = libslapd.la $(NSPR_LINK)
+librootdn_access_plugin_la_LDFLAGS = -avoid-version
+
+#------------------------
# libautomember-plugin
#------------------------
libautomember_plugin_la_SOURCES = ldap/servers/plugins/automember/automember.c
@@ -3784,6 +3804,17 @@ ldap/servers/plugins/roles/libroles_plugin_la-roles_plugin.lo: \
ldap/servers/plugins/roles/$(DEPDIR)/$(am__dirstamp)
libroles-plugin.la: $(libroles_plugin_la_OBJECTS) $(libroles_plugin_la_DEPENDENCIES)
$(libroles_plugin_la_LINK) -rpath $(serverplugindir) $(libroles_plugin_la_OBJECTS) $(libroles_plugin_la_LIBADD) $(LIBS)
+ldap/servers/plugins/rootdn_access/$(am__dirstamp):
+ @$(MKDIR_P) ldap/servers/plugins/rootdn_access
+ @: > ldap/servers/plugins/rootdn_access/$(am__dirstamp)
+ldap/servers/plugins/rootdn_access/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) ldap/servers/plugins/rootdn_access/$(DEPDIR)
+ @: > ldap/servers/plugins/rootdn_access/$(DEPDIR)/$(am__dirstamp)
+ldap/servers/plugins/rootdn_access/librootdn_access_plugin_la-rootdn_access.lo: \
+ ldap/servers/plugins/rootdn_access/$(am__dirstamp) \
+ ldap/servers/plugins/rootdn_access/$(DEPDIR)/$(am__dirstamp)
+librootdn-access-plugin.la: $(librootdn_access_plugin_la_OBJECTS) $(librootdn_access_plugin_la_DEPENDENCIES)
+ $(librootdn_access_plugin_la_LINK) -rpath $(serverplugindir) $(librootdn_access_plugin_la_OBJECTS) $(librootdn_access_plugin_la_LIBADD) $(LIBS)
ldap/servers/plugins/schema_reload/$(am__dirstamp):
@$(MKDIR_P) ldap/servers/plugins/schema_reload
@: > ldap/servers/plugins/schema_reload/$(am__dirstamp)
@@ -5017,6 +5048,8 @@ mostlyclean-compile:
-rm -f ldap/servers/plugins/roles/libroles_plugin_la-roles_cache.lo
-rm -f ldap/servers/plugins/roles/libroles_plugin_la-roles_plugin.$(OBJEXT)
-rm -f ldap/servers/plugins/roles/libroles_plugin_la-roles_plugin.lo
+ -rm -f ldap/servers/plugins/rootdn_access/librootdn_access_plugin_la-rootdn_access.$(OBJEXT)
+ -rm -f ldap/servers/plugins/rootdn_access/librootdn_access_plugin_la-rootdn_access.lo
-rm -f ldap/servers/plugins/schema_reload/libschemareload_plugin_la-schema_reload.$(OBJEXT)
-rm -f ldap/servers/plugins/schema_reload/libschemareload_plugin_la-schema_reload.lo
-rm -f ldap/servers/plugins/statechange/libstatechange_plugin_la-statechange.$(OBJEXT)
@@ -5714,6 +5747,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/rever/$(DEPDIR)/libdes_plugin_la-rever.Plo(a)am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/roles/$(DEPDIR)/libroles_plugin_la-roles_cache.Plo(a)am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/roles/$(DEPDIR)/libroles_plugin_la-roles_plugin.Plo(a)am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/rootdn_access/$(DEPDIR)/librootdn_access_plugin_la-rootdn_access.Plo(a)am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/schema_reload/$(DEPDIR)/libschemareload_plugin_la-schema_reload.Plo(a)am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/statechange/$(DEPDIR)/libstatechange_plugin_la-statechange.Plo(a)am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/syntaxes/$(DEPDIR)/libsyntax_plugin_la-bin.Plo(a)am__quote@
@@ -7758,6 +7792,13 @@ ldap/servers/plugins/roles/libroles_plugin_la-roles_plugin.lo: ldap/servers/plug
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroles_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ldap/servers/plugins/roles/libroles_plugin_la-roles_plugin.lo `test -f 'ldap/servers/plugins/roles/roles_plugin.c' || echo '$(srcdir)/'`ldap/servers/plugins/roles/roles_plugin.c
+ldap/servers/plugins/rootdn_access/librootdn_access_plugin_la-rootdn_access.lo: ldap/servers/plugins/rootdn_access/rootdn_access.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librootdn_access_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ldap/servers/plugins/rootdn_access/librootdn_access_plugin_la-rootdn_access.lo -MD -MP -MF ldap/servers/plugins/rootdn_access/$(DEPDIR)/librootdn_access_plugin_la-rootdn_access.Tpo -c -o ldap/servers/plugins/rootdn_access/librootdn_access_plugin_la-rootdn_access.lo `test -f 'ldap/servers/plugins/rootdn_access/rootdn_access.c' || echo '$(srcdir)/'`ldap/servers/plugins/rootdn_access/rootdn_access.c
+@am__fastdepCC_TRUE@ $(am__mv) ldap/servers/plugins/rootdn_access/$(DEPDIR)/librootdn_access_plugin_la-rootdn_access.Tpo ldap/servers/plugins/rootdn_access/$(DEPDIR)/librootdn_access_plugin_la-rootdn_access.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ldap/servers/plugins/rootdn_access/rootdn_access.c' object='ldap/servers/plugins/rootdn_access/librootdn_access_plugin_la-rootdn_access.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librootdn_access_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ldap/servers/plugins/rootdn_access/librootdn_access_plugin_la-rootdn_access.lo `test -f 'ldap/servers/plugins/rootdn_access/rootdn_access.c' || echo '$(srcdir)/'`ldap/servers/plugins/rootdn_access/rootdn_access.c
+
ldap/servers/plugins/schema_reload/libschemareload_plugin_la-schema_reload.lo: ldap/servers/plugins/schema_reload/schema_reload.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libschemareload_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ldap/servers/plugins/schema_reload/libschemareload_plugin_la-schema_reload.lo -MD -MP -MF ldap/servers/plugins/schema_reload/$(DEPDIR)/libschemareload_plugin_la-schema_reload.Tpo -c -o ldap/servers/plugins/schema_reload/libschemareload_plugin_la-schema_reload.lo `test -f 'ldap/servers/plugins/schema_reload/schema_reload.c' || echo '$(srcdir)/'`ldap/servers/plugins/schema_reload/schema_reload.c
@am__fastdepCC_TRUE@ $(am__mv) ldap/servers/plugins/schema_reload/$(DEPDIR)/libschemareload_plugin_la-schema_reload.Tpo ldap/servers/plugins/schema_reload/$(DEPDIR)/libschemareload_plugin_la-schema_reload.Plo
@@ -9779,6 +9820,7 @@ clean-libtool:
-rm -rf ldap/servers/plugins/retrocl/.libs ldap/servers/plugins/retrocl/_libs
-rm -rf ldap/servers/plugins/rever/.libs ldap/servers/plugins/rever/_libs
-rm -rf ldap/servers/plugins/roles/.libs ldap/servers/plugins/roles/_libs
+ -rm -rf ldap/servers/plugins/rootdn_access/.libs ldap/servers/plugins/rootdn_access/_libs
-rm -rf ldap/servers/plugins/schema_reload/.libs ldap/servers/plugins/schema_reload/_libs
-rm -rf ldap/servers/plugins/statechange/.libs ldap/servers/plugins/statechange/_libs
-rm -rf ldap/servers/plugins/syntaxes/.libs ldap/servers/plugins/syntaxes/_libs
@@ -10425,6 +10467,8 @@ distclean-generic:
-rm -f ldap/servers/plugins/rever/$(am__dirstamp)
-rm -f ldap/servers/plugins/roles/$(DEPDIR)/$(am__dirstamp)
-rm -f ldap/servers/plugins/roles/$(am__dirstamp)
+ -rm -f ldap/servers/plugins/rootdn_access/$(DEPDIR)/$(am__dirstamp)
+ -rm -f ldap/servers/plugins/rootdn_access/$(am__dirstamp)
-rm -f ldap/servers/plugins/schema_reload/$(DEPDIR)/$(am__dirstamp)
-rm -f ldap/servers/plugins/schema_reload/$(am__dirstamp)
-rm -f ldap/servers/plugins/statechange/$(DEPDIR)/$(am__dirstamp)
@@ -10475,7 +10519,7 @@ clean-am: clean-binPROGRAMS clean-generic clean-libtool clean-local \
distclean: distclean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
- -rm -rf ldap/libraries/libavl/$(DEPDIR) ldap/servers/plugins/acct_usability/$(DEPDIR) ldap/servers/plugins/acctpolicy/$(DEPDIR) ldap/servers/plugins/acl/$(DEPDIR) ldap/servers/plugins/automember/$(DEPDIR) ldap/servers/plugins/bitwise/$(DEPDIR) ldap/servers/plugins/chainingdb/$(DEPDIR) ldap/servers/plugins/collation/$(DEPDIR) ldap/servers/plugins/cos/$(DEPDIR) ldap/servers/plugins/deref/$(DEPDIR) ldap/servers/plugins/distrib/$(DEPDIR) ldap/servers/plugins/dna/$(DEPDIR) ldap/servers/plugins/http/$(DEPDIR) ldap/servers/plugins/linkedattrs/$(DEPDIR) ldap/servers/plugins/memberof/$(DEPDIR) ldap/servers/plugins/mep/$(DEPDIR) ldap/servers/plugins/pam_passthru/$(DEPDIR) ldap/servers/plugins/passthru/$(DEPDIR) ldap/servers/plugins/presence/$(DEPDIR) ldap/servers/plugins/pwdstorage/$(DEPDIR) ldap/servers/plugins/referint/$(DEPDIR) ldap/servers/plugins/replication/$(DEPDIR) ldap/servers/plugins/retrocl/$(DEPDIR) ldap/servers/plugins/rever/$(DEPDIR) ldap/servers/plugins/roles/$(DEPDIR)
ldap/servers/plugins/schema_reload/$(DEPDIR) ldap/servers/plugins/statechange/$(DEPDIR) ldap/servers/plugins/syntaxes/$(DEPDIR) ldap/servers/plugins/uiduniq/$(DEPDIR) ldap/servers/plugins/usn/$(DEPDIR) ldap/servers/plugins/views/$(DEPDIR) ldap/servers/slapd/$(DEPDIR) ldap/servers/slapd/back-ldbm/$(DEPDIR) ldap/servers/slapd/tools/$(DEPDIR) ldap/servers/slapd/tools/ldclt/$(DEPDIR) ldap/servers/slapd/tools/rsearch/$(DEPDIR) ldap/servers/snmp/$(DEPDIR) ldap/systools/$(DEPDIR) lib/base/$(DEPDIR) lib/ldaputil/$(DEPDIR) lib/libaccess/$(DEPDIR) lib/libadmin/$(DEPDIR) lib/libsi18n/$(DEPDIR)
+ -rm -rf ldap/libraries/libavl/$(DEPDIR) ldap/servers/plugins/acct_usability/$(DEPDIR) ldap/servers/plugins/acctpolicy/$(DEPDIR) ldap/servers/plugins/acl/$(DEPDIR) ldap/servers/plugins/automember/$(DEPDIR) ldap/servers/plugins/bitwise/$(DEPDIR) ldap/servers/plugins/chainingdb/$(DEPDIR) ldap/servers/plugins/collation/$(DEPDIR) ldap/servers/plugins/cos/$(DEPDIR) ldap/servers/plugins/deref/$(DEPDIR) ldap/servers/plugins/distrib/$(DEPDIR) ldap/servers/plugins/dna/$(DEPDIR) ldap/servers/plugins/http/$(DEPDIR) ldap/servers/plugins/linkedattrs/$(DEPDIR) ldap/servers/plugins/memberof/$(DEPDIR) ldap/servers/plugins/mep/$(DEPDIR) ldap/servers/plugins/pam_passthru/$(DEPDIR) ldap/servers/plugins/passthru/$(DEPDIR) ldap/servers/plugins/presence/$(DEPDIR) ldap/servers/plugins/pwdstorage/$(DEPDIR) ldap/servers/plugins/referint/$(DEPDIR) ldap/servers/plugins/replication/$(DEPDIR) ldap/servers/plugins/retrocl/$(DEPDIR) ldap/servers/plugins/rever/$(DEPDIR) ldap/servers/plugins/roles/$(DEPDIR)
ldap/servers/plugins/rootdn_access/$(DEPDIR) ldap/servers/plugins/schema_reload/$(DEPDIR) ldap/servers/plugins/statechange/$(DEPDIR) ldap/servers/plugins/syntaxes/$(DEPDIR) ldap/servers/plugins/uiduniq/$(DEPDIR) ldap/servers/plugins/usn/$(DEPDIR) ldap/servers/plugins/views/$(DEPDIR) ldap/servers/slapd/$(DEPDIR) ldap/servers/slapd/back-ldbm/$(DEPDIR) ldap/servers/slapd/tools/$(DEPDIR) ldap/servers/slapd/tools/ldclt/$(DEPDIR) ldap/servers/slapd/tools/rsearch/$(DEPDIR) ldap/servers/snmp/$(DEPDIR) ldap/systools/$(DEPDIR) lib/base/$(DEPDIR) lib/ldaputil/$(DEPDIR) lib/libaccess/$(DEPDIR) lib/libadmin/$(DEPDIR) lib/libsi18n/$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-hdr distclean-libtool distclean-tags
@@ -10531,7 +10575,7 @@ installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf $(top_srcdir)/autom4te.cache
- -rm -rf ldap/libraries/libavl/$(DEPDIR) ldap/servers/plugins/acct_usability/$(DEPDIR) ldap/servers/plugins/acctpolicy/$(DEPDIR) ldap/servers/plugins/acl/$(DEPDIR) ldap/servers/plugins/automember/$(DEPDIR) ldap/servers/plugins/bitwise/$(DEPDIR) ldap/servers/plugins/chainingdb/$(DEPDIR) ldap/servers/plugins/collation/$(DEPDIR) ldap/servers/plugins/cos/$(DEPDIR) ldap/servers/plugins/deref/$(DEPDIR) ldap/servers/plugins/distrib/$(DEPDIR) ldap/servers/plugins/dna/$(DEPDIR) ldap/servers/plugins/http/$(DEPDIR) ldap/servers/plugins/linkedattrs/$(DEPDIR) ldap/servers/plugins/memberof/$(DEPDIR) ldap/servers/plugins/mep/$(DEPDIR) ldap/servers/plugins/pam_passthru/$(DEPDIR) ldap/servers/plugins/passthru/$(DEPDIR) ldap/servers/plugins/presence/$(DEPDIR) ldap/servers/plugins/pwdstorage/$(DEPDIR) ldap/servers/plugins/referint/$(DEPDIR) ldap/servers/plugins/replication/$(DEPDIR) ldap/servers/plugins/retrocl/$(DEPDIR) ldap/servers/plugins/rever/$(DEPDIR) ldap/servers/plugins/roles/$(DEPDIR)
ldap/servers/plugins/schema_reload/$(DEPDIR) ldap/servers/plugins/statechange/$(DEPDIR) ldap/servers/plugins/syntaxes/$(DEPDIR) ldap/servers/plugins/uiduniq/$(DEPDIR) ldap/servers/plugins/usn/$(DEPDIR) ldap/servers/plugins/views/$(DEPDIR) ldap/servers/slapd/$(DEPDIR) ldap/servers/slapd/back-ldbm/$(DEPDIR) ldap/servers/slapd/tools/$(DEPDIR) ldap/servers/slapd/tools/ldclt/$(DEPDIR) ldap/servers/slapd/tools/rsearch/$(DEPDIR) ldap/servers/snmp/$(DEPDIR) ldap/systools/$(DEPDIR) lib/base/$(DEPDIR) lib/ldaputil/$(DEPDIR) lib/libaccess/$(DEPDIR) lib/libadmin/$(DEPDIR) lib/libsi18n/$(DEPDIR)
+ -rm -rf ldap/libraries/libavl/$(DEPDIR) ldap/servers/plugins/acct_usability/$(DEPDIR) ldap/servers/plugins/acctpolicy/$(DEPDIR) ldap/servers/plugins/acl/$(DEPDIR) ldap/servers/plugins/automember/$(DEPDIR) ldap/servers/plugins/bitwise/$(DEPDIR) ldap/servers/plugins/chainingdb/$(DEPDIR) ldap/servers/plugins/collation/$(DEPDIR) ldap/servers/plugins/cos/$(DEPDIR) ldap/servers/plugins/deref/$(DEPDIR) ldap/servers/plugins/distrib/$(DEPDIR) ldap/servers/plugins/dna/$(DEPDIR) ldap/servers/plugins/http/$(DEPDIR) ldap/servers/plugins/linkedattrs/$(DEPDIR) ldap/servers/plugins/memberof/$(DEPDIR) ldap/servers/plugins/mep/$(DEPDIR) ldap/servers/plugins/pam_passthru/$(DEPDIR) ldap/servers/plugins/passthru/$(DEPDIR) ldap/servers/plugins/presence/$(DEPDIR) ldap/servers/plugins/pwdstorage/$(DEPDIR) ldap/servers/plugins/referint/$(DEPDIR) ldap/servers/plugins/replication/$(DEPDIR) ldap/servers/plugins/retrocl/$(DEPDIR) ldap/servers/plugins/rever/$(DEPDIR) ldap/servers/plugins/roles/$(DEPDIR)
ldap/servers/plugins/rootdn_access/$(DEPDIR) ldap/servers/plugins/schema_reload/$(DEPDIR) ldap/servers/plugins/statechange/$(DEPDIR) ldap/servers/plugins/syntaxes/$(DEPDIR) ldap/servers/plugins/uiduniq/$(DEPDIR) ldap/servers/plugins/usn/$(DEPDIR) ldap/servers/plugins/views/$(DEPDIR) ldap/servers/slapd/$(DEPDIR) ldap/servers/slapd/back-ldbm/$(DEPDIR) ldap/servers/slapd/tools/$(DEPDIR) ldap/servers/slapd/tools/ldclt/$(DEPDIR) ldap/servers/slapd/tools/rsearch/$(DEPDIR) ldap/servers/snmp/$(DEPDIR) ldap/systools/$(DEPDIR) lib/base/$(DEPDIR) lib/ldaputil/$(DEPDIR) lib/libaccess/$(DEPDIR) lib/libadmin/$(DEPDIR) lib/libsi18n/$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
diff --git a/ldap/ldif/template-dse.ldif.in b/ldap/ldif/template-dse.ldif.in
index 5107d72..ddf2b35 100644
--- a/ldap/ldif/template-dse.ldif.in
+++ b/ldap/ldif/template-dse.ldif.in
@@ -734,6 +734,17 @@ nsslapd-plugintype: object
nsslapd-pluginenabled: off
nsslapd-plugin-depends-on-type: database
+dn: cn=RootDN Access Control,cn=plugins,cn=config
+objectclass: top
+objectclass: nsSlapdPlugin
+objectclass: extensibleObject
+cn: RootDN Access Control
+nsslapd-pluginpath: librootdn-access-plugin.so
+nsslapd-plugininitfunc: rootdn_init
+nsslapd-plugintype: internalpreoperation
+nsslapd-pluginenabled: off
+nsslapd-plugin-depends-on-type: database
+
dn: cn=ldbm database,cn=plugins,cn=config
objectclass: top
objectclass: nsSlapdPlugin
diff --git a/ldap/servers/plugins/rootdn_access/rootdn_access.c b/ldap/servers/plugins/rootdn_access/rootdn_access.c
new file mode 100644
index 0000000..7fb5615
--- /dev/null
+++ b/ldap/servers/plugins/rootdn_access/rootdn_access.c
@@ -0,0 +1,663 @@
+/** BEGIN COPYRIGHT BLOCK
+ * This Program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; version 2 of the License.
+ *
+ * This Program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/*
+ * Root DN Access Control plug-in
+ */
+#include "rootdn_access.h"
+#include <nspr.h>
+#include <time.h>
+#include <ctype.h>
+
+/*
+ * Add an entry like the following to dse.ldif to enable this plugin:
+ *
+ * dn: cn=RootDN Access Control,cn=plugins,cn=config
+ * objectclass: top
+ * objectclass: nsSlapdPlugin
+ * objectclass: extensibleObject
+ * cn: RootDN Access Control
+ * nsslapd-pluginpath: librootdn-access-plugin.so
+ * nsslapd-plugininitfunc: rootdn_init
+ * nsslapd-plugintype: rootdnpreoperation
+ * nsslapd-pluginenabled: on
+ * nsslapd-plugin-depends-on-type: database
+ * nsslapd-pluginid: rootdn-access-control
+ * rootdn-open-time: 0800
+ * rootdn-close-time: 1700
+ * rootdn-days-allowed: Mon, Tue, Wed, Thu, Fri
+ * rootdn-allow-host: *.redhat.com
+ * rootdn-allow-host: *.fedora.com
+ * rootdn-deny-host: dangerous.boracle.com
+ * rootdn-allow-ip: 127.0.0.1
+ * rootdn-allow-ip: 2000:db8:de30::11
+ * rootdn-deny-ip: 192.168.1.*
+ *
+ */
+
+/*
+ * Plugin Functions
+ */
+int rootdn_init(Slapi_PBlock *pb);
+static int rootdn_start(Slapi_PBlock *pb);
+static int rootdn_load_config(Slapi_PBlock *pb);
+static int rootdn_check_access(Slapi_PBlock *pb);
+static int rootdn_check_host_wildcard(char *host, char *client_host);
+static int rootdn_check_ip_wildcard(char *ip, char *client_ip);
+static int rootdn_preop_bind_init(Slapi_PBlock *pb);
+char * strToLower(char *str);
+
+/*
+ * Plug-in globals
+ */
+static void *_PluginID = NULL;
+static char *_PluginDN = NULL;
+static int g_plugin_started = 0;
+static int open_time = 0;
+static int close_time = 0;
+static char *daysAllowed = NULL;
+static char **hosts = NULL;
+static char **hosts_to_deny = NULL;
+static char **ips = NULL;
+static char **ips_to_deny = NULL;
+
+static Slapi_PluginDesc pdesc = { ROOTDN_FEATURE_DESC,
+ VENDOR,
+ DS_PACKAGE_VERSION,
+ ROOTDN_PLUGIN_DESC };
+
+/*
+ * Plugin identity functions
+ */
+void
+rootdn_set_plugin_id(void *pluginID)
+{
+ _PluginID = pluginID;
+}
+
+void *
+rootdn_get_plugin_id()
+{
+ return _PluginID;
+}
+
+void
+rootdn_set_plugin_dn(char *pluginDN)
+{
+ _PluginDN = pluginDN;
+}
+
+char *
+rootdn_get_plugin_dn()
+{
+ return _PluginDN;
+}
+
+
+int
+rootdn_init(Slapi_PBlock *pb){
+ int status = 0;
+ char *plugin_identity = NULL;
+
+ slapi_log_error(SLAPI_LOG_TRACE, ROOTDN_PLUGIN_SUBSYSTEM,
+ "--> rootdn_init\n");
+
+ /* Store the plugin identity for later use. Used for internal operations. */
+ slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &plugin_identity);
+ PR_ASSERT(plugin_identity);
+ rootdn_set_plugin_id(plugin_identity);
+
+ /* Register callbacks */
+ if(slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN, (void *) rootdn_start) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *) &pdesc) != 0 )
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM, "rootdn_init: failed to register plugin\n");
+ status = -1;
+ }
+
+ /* for this plugin we don't want to skip over root dn's when binding */
+ slapi_set_plugin_open_rootdn_bind(pb);
+
+ if (!status &&
+ slapi_register_plugin("internalpreoperation", /* op type */
+ 1, /* Enabled */
+ "rootdn_preop_bind_init", /* this function desc */
+ rootdn_preop_bind_init, /* init func */
+ ROOTDN_PLUGIN_DESC, /* plugin desc */
+ NULL, /* ? */
+ plugin_identity /* access control */
+ )) {
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM,
+ "rootdn_init: failed to register rootdn preoperation plugin\n");
+ status = -1;
+ }
+
+ /*
+ * Load the config
+ */
+ if(rootdn_load_config(pb) != 0){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM,
+ "rootdn_start: unable to load plug-in configuration\n");
+ return -1;
+ }
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, ROOTDN_PLUGIN_SUBSYSTEM,"<-- rootdn_init\n");
+ return status;
+}
+
+static int
+rootdn_preop_bind_init(Slapi_PBlock *pb)
+{
+ if(slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_PRE_BIND_FN, (void *) rootdn_check_access) != 0){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM,"rootdn_preop_bind_init: "
+ "failed to register function\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+rootdn_start(Slapi_PBlock *pb){
+ /* Check if we're already started */
+ if (g_plugin_started) {
+ goto done;
+ }
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, ROOTDN_PLUGIN_SUBSYSTEM, "--> rootdn_start\n");
+
+ g_plugin_started = 1;
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, ROOTDN_PLUGIN_SUBSYSTEM, "<-- rootdn_start\n");
+
+done:
+ return 0;
+}
+
+static int
+rootdn_load_config(Slapi_PBlock *pb)
+{
+ Slapi_Entry *e = NULL;
+ char *openTime, *closeTime;
+ char hour[3], min[3];
+ int result = 0;
+ int i;
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, ROOTDN_PLUGIN_SUBSYSTEM, "--> rootdn_load_config\n");
+
+ if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &e) == 0) && e){
+ /*
+ * Grab our plugin settings
+ */
+ openTime = slapi_entry_attr_get_charptr(e, "rootdn-open-time");
+ closeTime = slapi_entry_attr_get_charptr(e, "rootdn-close-time");
+ daysAllowed = slapi_entry_attr_get_charptr(e, "rootdn-days-allowed");
+ hosts = slapi_entry_attr_get_charray(e, "rootdn-allow-host");
+ hosts_to_deny = slapi_entry_attr_get_charray(e, "rootdn-deny-host");
+ ips = slapi_entry_attr_get_charray(e, "rootdn-allow-ip");
+ ips_to_deny = slapi_entry_attr_get_charray(e, "rootdn-deny-ip");
+ /*
+ * Validate out settings
+ */
+ if(daysAllowed){
+ if(strcspn(daysAllowed, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ,")){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM, "rootdn_load_config: "
+ "invalid rootdn-days-allowed value (%s), must be all letters, and comma separators\n",closeTime);
+ slapi_ch_free_string(&daysAllowed);
+ return -1;
+ }
+ daysAllowed = strToLower(daysAllowed);
+ }
+ if(openTime){
+ if (strcspn(openTime, "0123456789")){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM, "rootdn_load_config: "
+ "invalid rootdn-open-time value (%s), must be all digits\n",openTime);
+ slapi_ch_free_string(&openTime);
+ return -1;
+ }
+ if(strlen(openTime) != 4){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM, "rootdn_load_config: "
+ "invalid format for rootdn-open-time value (%s). Should be HHMM\n", openTime);
+ slapi_ch_free_string(&openTime);
+ return -1;
+ }
+ /*
+ * convert the time to all seconds
+ */
+ strncpy(hour, openTime,2);
+ strncpy(min, openTime+2,2);
+ open_time = (atoi(hour) * 3600) + (atoi(min) * 60);
+ }
+ if(closeTime){
+ if (strcspn(closeTime, "0123456789")){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM, "rootdn_load_config: "
+ "invalid rootdn-open-time value (%s), must be all digits, and should be HHMM\n",closeTime);
+ slapi_ch_free_string(&closeTime);
+ return -1;
+ }
+ if(strlen(closeTime) != 4){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM, "rootdn_load_config: "
+ "invalid format for rootdn-open-time value (%s), should be HHMM\n", closeTime);
+ slapi_ch_free_string(&closeTime);
+ return -1;
+ }
+ /*
+ * convert the time to all seconds
+ */
+
+ strncpy(hour, closeTime,2);
+ strncpy(min, closeTime+2,2);
+ close_time = (atoi(hour) * 3600) + (atoi(min) * 60);
+ }
+ if((openTime && closeTime == NULL) || (openTime == NULL && closeTime)){
+ /* If you are using TOD access control, you must have a open and close time */
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM, "rootdn_load_config: "
+ "there must be a open and a close time\n");
+ slapi_ch_free_string(&closeTime);
+ slapi_ch_free_string(&openTime);
+ return -1;
+ }
+ if(close_time && open_time && close_time <= open_time){
+ /* Make sure the closing time is greater than the open time */
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM, "rootdn_load_config: "
+ "the close time must be greater than the open time\n");
+ result = -1;
+ }
+ if(hosts){
+ for(i = 0; hosts[i] != NULL; i++){
+ if(strcspn(hosts[i], "0123456789.*-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM, "rootdn_load_config: "
+ "hostname (%s) contians invalid characters, skipping\n",hosts[i]);
+ slapi_ch_free_string(&hosts[i]);
+ hosts[i] = slapi_ch_strdup("!invalid");
+ continue;
+ }
+ }
+ }
+ if(hosts_to_deny){
+ for(i = 0; hosts_to_deny[i] != NULL; i++){
+ if(strcspn(hosts_to_deny[i], "0123456789.*-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM, "rootdn_load_config: "
+ "hostname (%s) contians invalid characters, skipping\n",hosts_to_deny[i]);
+ slapi_ch_free_string(&hosts_to_deny[i]);
+ hosts_to_deny[i] = slapi_ch_strdup("!invalid");
+ continue;
+ }
+ }
+ }
+ if(ips){
+ for(i = 0; ips[i] != NULL; i++){
+ if(strcspn(ips[i], "0123456789:ABCDEFabcdef.*")){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM, "rootdn_load_config: "
+ "IP address contains invalid characters (%s), skipping\n", ips[i]);
+ slapi_ch_free_string(&ips[i]);
+ ips[i] = slapi_ch_strdup("!invalid");
+ continue;
+ }
+ if(strstr(ips[i],":") == 0){
+ /*
+ * IPv4 - make sure it's just numbers, dots, and wildcard
+ */
+ if(strcspn(ips[i], "0123456789.*")){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM, "rootdn_load_config: "
+ "IPv4 address contains invalid characters (%s), skipping\n", ips[i]);
+ slapi_ch_free_string(&ips[i]);
+ ips[i] = slapi_ch_strdup("!invalid");
+ continue;
+ }
+ }
+ }
+ }
+ if(ips_to_deny){
+ for(i = 0; ips_to_deny[i] != NULL; i++){
+ if(strcspn(ips_to_deny[i], "0123456789:ABCDEFabcdef.*")){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM, "rootdn_load_config: "
+ "IP address contains invalid characters (%s), skipping\n", ips_to_deny[i]);
+ slapi_ch_free_string(&ips_to_deny[i]);
+ ips_to_deny[i] = slapi_ch_strdup("!invalid");
+ continue;
+ }
+ if(strstr(ips_to_deny[i],":") == 0){
+ /*
+ * IPv4 - make sure it's just numbers, dots, and wildcard
+ */
+ if(strcspn(ips_to_deny[i], "0123456789.*")){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM, "rootdn_load_config: "
+ "IPv4 address contains invalid characters (%s), skipping\n", ips_to_deny[i]);
+ slapi_ch_free_string(&ips_to_deny[i]);
+ ips_to_deny[i] = slapi_ch_strdup("!invalid");
+ continue;
+ }
+ }
+ }
+ }
+ slapi_ch_free_string(&openTime);
+ slapi_ch_free_string(&closeTime);
+ } else {
+ /* failed to get the plugin entry */
+ result = -1;
+ }
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, ROOTDN_PLUGIN_SUBSYSTEM, "<-- rootdn_load_config (%d)\n", result);
+
+ return result;
+}
+
+
+static int
+rootdn_check_access(Slapi_PBlock *pb){
+ PRNetAddr *client_addr = NULL;
+ PRHostEnt *host_entry = NULL;
+ time_t curr_time;
+ struct tm *timeinfo;
+ char *dnsName = NULL;
+ int isRoot = 0;
+ int rc = 0;
+ int i;
+
+ /*
+ * Verify this is a root DN
+ */
+ slapi_pblock_get ( pb, SLAPI_REQUESTOR_ISROOT, &isRoot );
+ if(!isRoot){
+ return 0;
+ }
+ /*
+ * grab the current time/info if we need it
+ */
+ if(open_time || daysAllowed){
+ time(&curr_time);
+ timeinfo = localtime(&curr_time);
+ }
+ /*
+ * First check TOD restrictions, continue through if we are in the open "window"
+ */
+ if(open_time){
+ int curr_total;
+
+ curr_total = (timeinfo->tm_hour * 3600) + (timeinfo->tm_min * 60);
+
+ if((curr_total < open_time) || (curr_total >= close_time)){
+ slapi_log_error(SLAPI_LOG_PLUGIN, ROOTDN_PLUGIN_SUBSYSTEM, "rootdn_check_access: bind not in the "
+ "allowed time window\n");
+ return -1;
+ }
+ }
+ /*
+ * Check if today is an allowed day
+ */
+ if(daysAllowed){
+ char *timestr;
+ char day[4];
+ char *today = day;
+
+ timestr = asctime(timeinfo); // DDD MMM dd hh:mm:ss YYYY
+ memmove(day, timestr, 3); // we only want the day
+ today = strToLower(today);
+
+ if(!strstr(today, daysAllowed)){
+ slapi_log_error(SLAPI_LOG_PLUGIN, ROOTDN_PLUGIN_SUBSYSTEM, "rootdn_check_access: bind not allowed for today\n");
+ return -1;
+ }
+ }
+ /*
+ * Check the host restrictions, deny always overrides allow
+ */
+ if(hosts || hosts_to_deny){
+ char buf[PR_NETDB_BUF_SIZE];
+ char *host;
+
+ /*
+ * Get the client address
+ */
+ client_addr = (PRNetAddr *)slapi_ch_malloc(sizeof(PRNetAddr));
+ if ( slapi_pblock_get( pb, SLAPI_CONN_CLIENTNETADDR, client_addr ) != 0 ) {
+ slapi_log_error( SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM, "rootdn_check_access: Could not get client address for hosts.\n" );
+ rc = -1;
+ goto free_and_return;
+ }
+ /*
+ * Get the hostname from the client address
+ */
+ host_entry = (PRHostEnt *)slapi_ch_malloc( sizeof(PRHostEnt) );
+ if ( PR_GetHostByAddr(client_addr, buf, sizeof(buf), host_entry ) == PR_SUCCESS ) {
+ if ( host_entry->h_name != NULL ) {
+ /* copy the hostname */
+ dnsName = slapi_ch_strdup( host_entry->h_name );
+ } else {
+ /* no hostname */
+ slapi_log_error( SLAPI_LOG_PLUGIN, ROOTDN_PLUGIN_SUBSYSTEM, "rootdn_check_access: client address missing hostname\n");
+ rc = -1;
+ goto free_and_return;
+ }
+ } else {
+ slapi_log_error( SLAPI_LOG_PLUGIN, ROOTDN_PLUGIN_SUBSYSTEM, "rootdn_check_access: client IP address could not be resolved\n");
+ rc = -1;
+ goto free_and_return;
+ }
+ /*
+ * Now we have our hostname, now do our checks
+ */
+ if(hosts_to_deny){
+ for(i = 0; hosts_to_deny[i] != NULL; i++){
+ host = hosts_to_deny[i];
+ /* check for wild cards */
+ if(host[0] == '*'){
+ if(rootdn_check_host_wildcard(host, dnsName) == 0){
+ /* match, return failure */
+ rc = -1;
+ goto free_and_return;
+ }
+ } else {
+ if(strcasecmp(host,dnsName) == 0){
+ /* we have a match, return failure */
+ rc = -1;
+ goto free_and_return;
+ }
+ }
+ }
+ rc = 0;
+ }
+ if(hosts){
+ for(i = 0; hosts[i] != NULL; i++){
+ host = hosts[i];
+ /* check for wild cards */
+ if(host[0] == '*'){
+ if(rootdn_check_host_wildcard(host, dnsName) == 0){
+ /* match */
+ rc = 0;
+ goto free_and_return;
+ }
+ } else {
+ if(strcasecmp(host,dnsName) == 0){
+ /* we have a match, */
+ rc = 0;
+ goto free_and_return;
+ }
+ }
+ }
+ rc = -1;
+ }
+ }
+ /*
+ * Check the IP address restrictions, deny always overrides allow
+ */
+ if(ips || ips_to_deny){
+ char ip_str[256];
+ char *ip;
+ int ip_len, i;
+
+ if(client_addr == NULL){
+ client_addr = (PRNetAddr *)slapi_ch_malloc(sizeof(PRNetAddr));
+ if ( slapi_pblock_get( pb, SLAPI_CONN_CLIENTNETADDR, client_addr ) != 0 ) {
+ slapi_log_error( SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM, "rootdn_check_access: Could not get client address for IP.\n" );
+ rc = -1;
+ goto free_and_return;
+ }
+ }
+ /*
+ * Check if we are IPv4, so we can grab the correct IP addr for "ip_str"
+ */
+ if ( PR_IsNetAddrType( client_addr, PR_IpAddrV4Mapped ) ) {
+ PRNetAddr v4addr;
+ memset( &v4addr, 0, sizeof( v4addr ) );
+ v4addr.inet.family = PR_AF_INET;
+ v4addr.inet.ip = client_addr->ipv6.ip.pr_s6_addr32[3];
+ if( PR_NetAddrToString( &v4addr, ip_str, sizeof( ip_str )) != PR_SUCCESS){
+ slapi_log_error( SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM, "rootdn_check_access: Could not get IPv4 from client address.\n" );
+ rc = -1;
+ goto free_and_return;
+ }
+ } else {
+ if( PR_NetAddrToString(client_addr, ip_str, sizeof(ip_str)) != PR_SUCCESS){
+ slapi_log_error( SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM, "rootdn_check_access: Could not get IPv6 from client address.\n" );
+ rc = -1;
+ goto free_and_return;
+ }
+ }
+ /*
+ * Now we have our IP address, do our checks
+ */
+ if(ips_to_deny){
+ for(i = 0; ips_to_deny[i] != NULL; i++){
+ ip = ips_to_deny[i];
+ ip_len = strlen(ip);
+ if(ip[ip_len - 1] == '*'){
+ if(rootdn_check_ip_wildcard(ips_to_deny[i], ip_str) == 0){
+ /* match, return failure */
+ rc = -1;
+ goto free_and_return;
+ }
+ } else {
+ if(strcasecmp(ip_str, ip)==0){
+ /* match, return failure */
+ rc = -1;
+ goto free_and_return;
+ }
+ }
+ }
+ rc = 0;
+ }
+ if(ips){
+ for(i = 0; ips[i] != NULL; i++){
+ ip = ips[i];
+ ip_len = strlen(ip);
+ if(ip[ip_len - 1] == '*'){
+ if(rootdn_check_ip_wildcard(ip, ip_str) == 0){
+ /* match, return success */
+ rc = 0;
+ goto free_and_return;
+ }
+ } else {
+ if(strcasecmp(ip_str, ip)==0){
+ /* match, return success */
+ rc = 0;
+ goto free_and_return;
+ }
+ }
+ }
+ rc = -1;
+ }
+ }
+
+free_and_return:
+ slapi_ch_free((void **)&client_addr);
+ slapi_ch_free((void **)&host_entry);
+ slapi_ch_free_string(&dnsName);
+
+ return rc;
+}
+
+static int
+rootdn_check_host_wildcard(char *host, char *client_host)
+{
+ int host_len = strlen(host);
+ int client_len = strlen(client_host);
+ int i, j;
+ /*
+ * Start at the end of the string and move backwards, and skip the first char "*"
+ */
+ if(client_len < host_len){
+ /* this can't be a match */
+ return -1;
+ }
+ for(i = host_len - 1, j = client_len - 1; i > 0; i--, j--){
+ if(host[i] != client_host[j]){
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+rootdn_check_ip_wildcard(char *ip, char *client_ip)
+{
+ int ip_len = strlen(ip);
+ int i;
+ /*
+ * Start at the beginning of the string and move forward, and skip the last char "*"
+ */
+ if(strlen(client_ip) < ip_len){
+ /* this can't be a match */
+ return -1;
+ }
+ for(i = 0; i < ip_len - 1; i++){
+ if(ip[i] != client_ip[i]){
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+char *
+strToLower(char *str){
+ int i;
+
+ for(i = 0; i < strlen(str); i++){
+ str[i] = tolower(str[i]);
+ }
+ return str;
+}
+
+
diff --git a/ldap/servers/plugins/rootdn_access/rootdn_access.h b/ldap/servers/plugins/rootdn_access/rootdn_access.h
new file mode 100644
index 0000000..80b8d4a
--- /dev/null
+++ b/ldap/servers/plugins/rootdn_access/rootdn_access.h
@@ -0,0 +1,57 @@
+/** BEGIN COPYRIGHT BLOCK
+ * This Program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; version 2 of the License.
+ *
+ * This Program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/*
+ * Root DN access control plug-in header file
+ */
+#include "slapi-plugin.h"
+#include <nspr.h>
+#include <time.h>
+#include <ctype.h>
+
+#define ROOTDN_PLUGIN_SUBSYSTEM "rootdn-access-control-plugin"
+#define ROOTDN_FEATURE_DESC "Root DN Access Control"
+#define ROOTDN_PLUGIN_DESC "Root DN Access Control plugin"
+#define ROOTDN_PLUGIN_TYPE_DESC "Root DN Access Control plugin"
+
+
+
diff --git a/ldap/servers/slapd/bind.c b/ldap/servers/slapd/bind.c
index d725d5c..d4d3b49 100644
--- a/ldap/servers/slapd/bind.c
+++ b/ldap/servers/slapd/bind.c
@@ -614,21 +614,41 @@ do_bind( Slapi_PBlock *pb )
Slapi_Value cv;
slapi_value_init_berval(&cv,&cred);
- /* right dn and passwd - authorize */
+ /*
+ * Call pre bind root dn plugin for checking root dn access control.
+ *
+ * Do this before checking the password so that we give a consistent error,
+ * regardless if the password is correct or not. Or else it would still be
+ * possible to brute force guess the password even though access would still
+ * be denied.
+ */
+ if (plugin_call_plugins(pb, SLAPI_PLUGIN_INTERNAL_PRE_BIND_FN) != 0){
+ send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "RootDN access control violation", 0, NULL );
+ slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsBindSecurityErrors);
+ value_done(&cv);
+ goto free_and_return;
+ }
+ /*
+ * Check the dn and password
+ */
if ( is_root_dn_pw( slapi_sdn_get_ndn(sdn), &cv )) {
- bind_credentials_set( pb->pb_conn, SLAPD_AUTH_SIMPLE,
- slapi_ch_strdup( slapi_sdn_get_ndn(sdn) ),
+ /*
+ * right dn and passwd - authorize
+ */
+ bind_credentials_set( pb->pb_conn, SLAPD_AUTH_SIMPLE, slapi_ch_strdup(slapi_sdn_get_ndn(sdn)),
NULL, NULL, NULL , NULL);
-
- /* right dn, wrong passwd - reject with invalid creds */
} else {
- send_ldap_result( pb, LDAP_INVALID_CREDENTIALS, NULL,
- NULL, 0, NULL );
+ /*
+ * right dn, wrong passwd - reject with invalid credentials
+ */
+ send_ldap_result( pb, LDAP_INVALID_CREDENTIALS, NULL, NULL, 0, NULL );
/* increment BindSecurityErrorcount */
slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsBindSecurityErrors);
value_done(&cv);
goto free_and_return;
}
+
value_done(&cv);
}
diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c
index 76c031a..4be8efd 100644
--- a/ldap/servers/slapd/pblock.c
+++ b/ldap/servers/slapd/pblock.c
@@ -1062,6 +1062,14 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
(*(IFP *)value) = pblock->pb_plugin->plg_internal_post_delete;
break;
+ /* rootDN pre bind operation plugin */
+ case SLAPI_PLUGIN_INTERNAL_PRE_BIND_FN:
+ if (pblock->pb_plugin->plg_type != SLAPI_PLUGIN_INTERNAL_PREOPERATION) {
+ return( -1 );
+ }
+ (*(IFP *)value) = pblock->pb_plugin->plg_internal_pre_bind;
+ break;
+
/* backend pre txn operation plugin */
case SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN:
if (pblock->pb_plugin->plg_type != SLAPI_PLUGIN_BETXNPREOPERATION) {
@@ -2620,6 +2628,12 @@ slapi_pblock_set( Slapi_PBlock *pblock, int arg, void *value )
}
pblock->pb_plugin->plg_internal_pre_delete = (IFP) value;
break;
+ case SLAPI_PLUGIN_INTERNAL_PRE_BIND_FN:
+ if (pblock->pb_plugin->plg_type != SLAPI_PLUGIN_INTERNAL_PREOPERATION) {
+ return( -1 );
+ }
+ pblock->pb_plugin->plg_internal_pre_bind = (IFP) value;
+ break;
/* internal postoperation plugin */
case SLAPI_PLUGIN_INTERNAL_POST_MODIFY_FN:
diff --git a/ldap/servers/slapd/plugin.c b/ldap/servers/slapd/plugin.c
index 8aa95ac..436cc02 100644
--- a/ldap/servers/slapd/plugin.c
+++ b/ldap/servers/slapd/plugin.c
@@ -363,6 +363,7 @@ plugin_call_plugins( Slapi_PBlock *pb, int whichfunction )
case SLAPI_PLUGIN_INTERNAL_PRE_MODRDN_FN:
case SLAPI_PLUGIN_INTERNAL_PRE_ADD_FN:
case SLAPI_PLUGIN_INTERNAL_PRE_DELETE_FN:
+ case SLAPI_PLUGIN_INTERNAL_PRE_BIND_FN:
plugin_list_number= PLUGIN_LIST_INTERNAL_PREOPERATION;
break;
case SLAPI_PLUGIN_INTERNAL_POST_MODIFY_FN:
@@ -387,6 +388,7 @@ plugin_call_plugins( Slapi_PBlock *pb, int whichfunction )
do_op = 1; /* always allow backend callbacks (even during startup) */
break;
}
+
if(plugin_list_number!=-1 && do_op)
{
/* We stash the pblock plugin pointer to preserve the callers context */
@@ -1705,7 +1707,7 @@ plugin_get_type_and_list(
} else if ( strcasecmp( plugintype, "index" ) == 0 ) {
*type = SLAPI_PLUGIN_INDEX;
plugin_list_index= PLUGIN_LIST_INDEX;
- } else {
+ } else {
return( 1 ); /* unknown plugin type - pass to backend */
}
@@ -3205,3 +3207,10 @@ slapi_get_plugin_default_config(char *type, Slapi_ValueSet **valueset)
return rc;
}
+
+void
+slapi_set_plugin_open_rootdn_bind(Slapi_PBlock *pb){
+ struct pluginconfig *config = &pb->pb_plugin->plg_conf;
+
+ ptd_set_special_data(&(config->plgc_bind_subtrees), PLGC_DATA_BIND_ROOT);
+}
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 3138ed3..d0f2b33 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1004,11 +1004,13 @@ struct slapdplugin {
IFP plg_un_internal_pre_modrdn; /* modrdn */
IFP plg_un_internal_pre_add; /* add */
IFP plg_un_internal_pre_delete; /* delete */
+ IFP plg_un_internal_pre_bind; /* bind */
} plg_un_internal_pre;
#define plg_internal_pre_modify plg_un.plg_un_internal_pre.plg_un_internal_pre_modify
#define plg_internal_pre_modrdn plg_un.plg_un_internal_pre.plg_un_internal_pre_modrdn
#define plg_internal_pre_add plg_un.plg_un_internal_pre.plg_un_internal_pre_add
#define plg_internal_pre_delete plg_un.plg_un_internal_pre.plg_un_internal_pre_delete
+#define plg_internal_pre_bind plg_un.plg_un_internal_pre.plg_un_internal_pre_bind
/* internal post-operation plugin structure */
struct plg_un_internal_post_operation {
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 823652a..63c37f0 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -6305,6 +6305,7 @@ typedef struct slapi_plugindesc {
#define SLAPI_PLUGIN_INTERNAL_PRE_MODIFY_FN 421
#define SLAPI_PLUGIN_INTERNAL_PRE_MODRDN_FN 422
#define SLAPI_PLUGIN_INTERNAL_PRE_DELETE_FN 423
+#define SLAPI_PLUGIN_INTERNAL_PRE_BIND_FN 424
/* preoperation plugin to the backend */
#define SLAPI_PLUGIN_BE_PRE_ADD_FN 450
@@ -7078,6 +7079,8 @@ uint32_t slapi_str_to_u32(const char *s);
*/
uint64_t slapi_str_to_u64(const char *s);
+void slapi_set_plugin_open_rootdn_bind(Slapi_PBlock *pb);
+
#ifdef __cplusplus
}
#endif
11 years, 6 months
Changes to 'refs/tags/389-ds-base-1.2.11.4'
by Richard Allen Megginson
Changes since 389-ds-base-1.2.6.a1:
Charles Lopes (1):
Bug #361: Bad DNs in ACIs can segfault ns-slapd
Endi S. Dewata (168):
Bug 545620 - Password cannot start with minus sign
Bug 538525 - Ability to create instance as non-root user
Bug 570542 - Root password cannot contain matching curly braces
Bug 470684 - Pam_passthru plugin doesn't verify account activation
Bug 573375 - MODRDN operation not logged
Bug 520151 - Error when modifying userPassword with proxy user
Bug 455489 - Address compiler warnings about strict-aliasing rules
Bug 566320 - RFE: add exception to removal of attributes in cn=config for aci
Bug 566043 - startpid file is only cleaned by initscript runs
Bug 584109 - Slapd crashes while parsing DNA configuration
Bug 542570 - Directory Server port number is not validated in the beginning.
Bug 145181 - Plugin target/bind subtrees only take 1 value.
Bug 614511 - fix coverify Defect Type: Null pointer dereferences issues 11846 - 11891
Bug 614511 - fix coverify Defect Type: Null pointer dereferences issues 11846 - 11891
Bug 614511 - fix coverify Defect Type: Null pointer dereferences issues 11846 - 11891
Bug 614511 - fix coverify Defect Type: Null pointer dereferences issues 11846 - 11891
Bug 614511 - fix coverify Defect Type: Null pointer dereferences issues 11846 - 11891
Bug 614511 - fix coverify Defect Type: Null pointer dereferences issues 11846 - 11891
Bug 614511 - fix coverify Defect Type: Null pointer dereferences issues 11846 - 11891
Bug 614511 - fix coverify Defect Type: Null pointer dereferences issues 11846 - 11891
Bug 614511 - fix coverify Defect Type: Null pointer dereferences issues 11846 - 11891
Bug 614511 - fix coverify Defect Type: Null pointer dereferences issues 11846 - 11891
Bug 614511 - fix coverify Defect Type: Null pointer dereferences issues 11846 - 11891
Bug 614511 - fix coverify Defect Type: Null pointer dereferences issues 11846 - 11891
Bug 614511 - fix coverify Defect Type: Null pointer dereferences issues 11846 - 11891
Bug 614511 - fix coverify Defect Type: Null pointer dereferences issues 11846 - 11891
Bug 614511 - fix coverify Defect Type: Null pointer dereferences issues 11846 - 11891
Bug 614511 - fix coverify Defect Type: Null pointer dereferences issues 11846 - 11891
Bug 614511 - fix coverify Defect Type: Null pointer dereferences issues 11846 - 11891
Bug 614511 - fix coverify Defect Type: Null pointer dereferences issues 11846 - 11891
Bug 614511 - fix coverify Defect Type: Null pointer dereferences issues 11846 - 11891
Bug 614511 - fix coverify Defect Type: Null pointer dereferences issues 11846 - 11891
Bug 614511 - fix coverify Defect Type: Null pointer dereferences issues 11846 - 11891
Bug 614511 - fix coverify Defect Type: Null pointer dereferences issues 11846 - 11891
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 619122 - fix coverify Defect Type: Resource leaks issues CID 11975 - 12053
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 616500 - fix coverify Defect Type: Resource leaks issues CID 12094 - 12136
Bug 616500 - fix coverify Defect Type: Resource leaks issues CID 12094 - 12136
Bug 616500 - fix coverify Defect Type: Resource leaks issues CID 12094 - 12136
Bug 616500 - fix coverify Defect Type: Resource leaks issues CID 12094 - 12136
Bug 616500 - fix coverify Defect Type: Resource leaks issues CID 12094 - 12136
Bug 616500 - fix coverify Defect Type: Resource leaks issues CID 12094 - 12136
Bug 616500 - fix coverify Defect Type: Resource leaks issues CID 12094 - 12136
Bug 616500 - fix coverify Defect Type: Resource leaks issues CID 12094 - 12136
Bug 616500 - fix coverify Defect Type: Resource leaks issues CID 12094 - 12136
Bug 616500 - fix coverify Defect Type: Resource leaks issues CID 12094 - 12136
Bug 616500 - fix coverify Defect Type: Resource leaks issues CID 12094 - 12136
Bug 616500 - fix coverify Defect Type: Resource leaks issues CID 12094 - 12136
Bug 616500 - fix coverify Defect Type: Resource leaks issues CID 12094 - 12136
Bug 616500 - fix coverify Defect Type: Resource leaks issues CID 12094 - 12136
Bug 616500 - fix coverify Defect Type: Resource leaks issues CID 12094 - 12136
Bug 616500 - fix coverify Defect Type: Resource leaks issues CID 12094 - 12136
Bug 616500 - fix coverify Defect Type: Resource leaks issues CID 12094 - 12136
Bug 610119 - fix coverify Defect Type: Null pointer dereferences issues 12167 - 12199
Bug 610119 - fix coverify Defect Type: Null pointer dereferences issues 12167 - 12199
Bug 610119 - fix coverify Defect Type: Null pointer dereferences issues 12167 - 12199
Bug 610119 - fix coverify Defect Type: Null pointer dereferences issues 12167 - 12199
Bug 610119 - fix coverify Defect Type: Null pointer dereferences issues 12167 - 12199
Bug 610119 - fix coverify Defect Type: Null pointer dereferences issues 12167 - 12199
Bug 610119 - fix coverify Defect Type: Null pointer dereferences issues 12167 - 12199
Bug 610119 - fix coverify Defect Type: Null pointer dereferences issues 12167 - 12199
Bug 610119 - fix coverify Defect Type: Null pointer dereferences issues 12167 - 12199
Bug 610119 - fix coverify Defect Type: Null pointer dereferences issues 12167 - 12199
Bug 610119 - fix coverify Defect Type: Null pointer dereferences issues 12167 - 12199
Bug 610119 - fix coverify Defect Type: Null pointer dereferences issues 12167 - 12199
Bug 610119 - fix coverify Defect Type: Null pointer dereferences issues 12167 - 12199
Bug 610119 - fix coverify Defect Type: Null pointer dereferences issues 12167 - 12199
Bug 610119 - fix coverify Defect Type: Null pointer dereferences issues 12167 - 12199
Bug 610119 - fix coverify Defect Type: Null pointer dereferences issues 12167 - 12199
Bug 611790 - fix coverify Defect Type: Null pointer dereferences issues 11940 - 12166
Bug 611790 - fix coverify Defect Type: Null pointer dereferences issues 11940 - 12166
Bug 611790 - fix coverify Defect Type: Null pointer dereferences issues 11940 - 12166
Bug 611790 - fix coverify Defect Type: Null pointer dereferences issues 11940 - 12166
Bug 611790 - fix coverify Defect Type: Null pointer dereferences issues 11940 - 12166
Bug 611790 - fix coverify Defect Type: Null pointer dereferences issues 11940 - 12166
Bug 611790 - fix coverify Defect Type: Null pointer dereferences issues 11940 - 12166
Bug 611790 - fix coverify Defect Type: Null pointer dereferences issues 11940 - 12166
Bug 611790 - fix coverify Defect Type: Null pointer dereferences issues 11940 - 12166
Bug 611790 - fix coverify Defect Type: Null pointer dereferences issues 11940 - 12166
Bug 611790 - fix coverify Defect Type: Null pointer dereferences issues 11940 - 12166
Bug 611790 - fix coverify Defect Type: Null pointer dereferences issues 11940 - 12166
Bug 611790 - fix coverify Defect Type: Null pointer dereferences issues 11940 - 12166
Bug 611790 - fix coverify Defect Type: Null pointer dereferences issues 11940 - 12166
Bug 628096 - spurious error message from /sbin/service when doing a stop on no instances
Bug 573889 - Migration does not remove deprecated schema
Bug 606545 - core schema should include numSubordinates
Bug 643979 - Strange byte sequence for attribute with no values (nsslapd-referral)
Endi Sukma Dewata (16):
Bug 630092 - Coverity #12117: Resource leaks issues
Bug 630092 - Coverity #15478: Resource leaks issues
Bug 630092 - Coverity #15479: Resource leaks issues
Bug 630092 - Coverity #15481: Resource leaks issues
Bug 630092 - Coverity #15482: Resource leaks issues
Bug 630092 - Coverity #15483: Resource leaks issues
Bug 630092 - Coverity #15484: Resource leaks issues
Bug 630092 - Coverity #15485: Resource leaks issues
Bug 630092 - Coverity #15487: Resource leaks issues
Bug 630092 - Coverity #15490: Resource leaks issues
Bug 630092 - Coverity #15497: Resource leaks issues
Bug 630092 - Coverity #11991: Resource leaks issues
Bug 630092 - Coverity #12000: Resource leaks issues
Bug 630092 - Coverity #12003: Resource leaks issues
Bug 630092 - Coverity #11985: Resource leaks issues
Bug 630092 - Coverity #11992,11993: Resource leaks issues
Jeroen van Meeuwen (Kolab Systems) (1):
Suppress alert on unavailable port with forced setup
Mark Reynolds (48):
Ticket #71 - unable to delete managed entry config
Ticket #159 - Managed Entry Plugin runs against managed entries upon any update without validating
Ticket #177 - logconv.pl doesn't detect restarts
Merge branch 'ticket159'
Ticket #49 - better handling for server shutdown while long running tasks are active
Ticket #50 - server should not call a plugin after the plugin close function is calle
Updated for ticket#50
Ticket #55 - Limit of 1024 characters for nsMatchingRule
Ticket #140 - incorrect memset parameters
Revert "Ticket #140 - incorrect memset parameters"
Revert "Ticket #55 - Limit of 1024 characters for nsMatchingRule"
Ticket #38 - nisDomain schema is incorrect
Ticket #6 - protocol error from proxied auth operation
Ticket #55 - Limit of 1024 characters for nsMatchingRule
Ticket #39 - Account Policy Plugin does not work for simple binds when PAM Pass Through Auth plugin is enabled
Ticket 175 - logconv.pl improvements
Ticket 175 - minor fixes
Ticket #17 - Replication optimizations
Ticket #17 - new replication optimizations
Ticket #129 - Should only update modifyTimestamp/modifiersName on MODIFY ops
Ticket #111 - ability to control behavior of modifyTimestamp/modifiersName
Ticket #211 - dnaNextValue gets incremented even if the user addition fails
Ticket #74 - Add schema for DNA plugin (RFE)
Ticket #306 - void function cannot return value
Ticket #302 - use thread local storage for internalModifiersName & internalCreatorsName
Schema Reload crash fix
Ticket #291 - cannot use & in a sasl map search filter
Ticket #305 - Certain CMP operations hang or cause ns-slapd to crash
Ticket #191 - Implement SO_KEEPALIVE in network calls
Config changes fail because of unknown attribute "internalModifiersname"
Ticket #292 - logconv.pl reporting unindexed search with different search base than shown in access logs
Ticket #308 - Automembership plugin fails if data and config area mixed in the plugin configuration
Ticket #271 - replication code cleanup
TIcket #285 - compilation fixes for '--format-security'
Ticket #271 - Slow shutdown when you have 100+ replication agreements
Ticket #24 - Add nsTLS1 to the DS schema
Ticket #319 - ldap-agent crashes on start with signal SIGSEGV
Ticket #20 - Allow automember to work on entries that have already been added
Ticket #315 - ns-slapd exits/crashes if /var fills up
Ticket #315 - small fix to libglobs
Ticket #183 - passwordMaxFailure should lockout password one sooner - and should be configurable to avoid regressions
Coverity Fixes
Ticket #325 - logconv.pl : use of getopts to parse command line options
Ticket #183 - passwordMaxFailure should lockout password one sooner
Ticket #207 - [RFE] enable attribute that tracks when a password was last set
Ticket #214 - Adding Replication agreement should complain if required nsds5ReplicaCredentials not supplied
Ticket #337 - Improve CLEANRUV task
Ticket #321 - krbExtraData is being null modified and replicated on each ssh login
Nathan Kinder (193):
Bug 549554 - Trim single-valued attributes before sending to AD
Improve search for pcre header file
Bug 434735 - Allow SASL ANONYMOUS mech to work
Bug 570912 - Avoid selinux context conflict with httpd
Allow instance name to be parsed from start-slapd
Add managed entries plug-in
Bug 572355 - Label instance files and ports during upgrade.
Bug 578863 - Password modify extop needs to send referrals on replicas
Bug 584156 - Remove ldapi socket file during upgrade
Fix rsearch usage of name files for random filters
Bug 584497 - Allow DNA plugin to set same value on multiple attributes
Add replication session hooks
Correct function prototype for repl session hook
Bug 592389 - Set anonymous resource limits properly
Bug 601433 - Add man pages for start-dirsrv and related commands
Bug 604263 - Fix memory leak when password change is rejected
Bug 612242 - membership change on DS does not show on AD
Bug 613833 - Allow dirsrv_t to bind to rpc ports
Bug 594745 - Get rid of dirsrv_lib_t label
Bug 620927 - Allow multiple membership attributes in memberof plugin
Bug 612264 - ACI issue with (targetattr='userPassword')
Bug 630098 - fix coverity Defect Type: Code maintainability issues
Bug 630098 - fix coverity Defect Type: Code maintainability issues
Bug 630093 - (cov#15511) Don't use unintialized search_results in refint plugin
Bug 630093 - (cov#15518) Need to intialize fd in ldbm2ldif code
Bug 630096 - (cov#11778) check return value of ldap_parse_result
Bug 630096 - (cov#15446) check return value of ber_scanf()
Bug 630096 - (cov#15449,15450) Check return value of stat()
Bug 630096 - (cov#15448) Check return value of cache_replace()
Bug 630096 - (cov#15447) - Check return value of idl_append_extend()
Bug 630090 - (cov#11974) Remove unused ACL functions
Bug 630090 - (cov#15445) Fix illegal free in archive code
Bug 630094 - (cov#11818) Fix unreachable return in snmp subagent
Bug 630094 - (cov#15451) Get rid of unreachable free statements
Bug 630094 - (cov#15452) Remove NULL checking for op_string
Bug 630094 - (cov#15453) Eliminate NULL check for local_newentry
Bug 630094 - (cov#15454) Fix deadcode issue in mapping tree code
Bug 630094 - (cov#15455) Remove deadcode in attr_index_config()
Bug 630094 - (cov#15456) Remove NULL check for srdn in import code
Bug 630094 - (cov#15457) Remove deadcode in import code
Bug 630094 - (cov#15458) Fix deadcode issue in moddn code
Bug 630094 - (cov#15459) Remove NULL check for srdn in ldif2ldbm code
Bug 630094 - (cov#15520) Fix unreachable code issue if perfctrs code
Bug 630094 - (cov#15581) Add missing breaks in agt_mopen_stats()
Bug 690090 - (cov#11974) Remove additional unused ACL functions
Bug 630091 - (cov#15512) Fix usage of uninitialized bervals
Bug 630091 - (cov#15513) Fix usage of uninitialized bervals
Bug 630091 - (cov#15514) Initialize DBT in entryrdn_get_parent()
Bug 630091 - (cov#15515) Use of uninitialized array in index config code
Bug 630091 - (cov#15516,15517) Initialize pointers before attempting to free
Bug 630091 - (cov#15519) Initialize bervals in search_easter_egg()
Bug 630091 - (cov#15582) Free of uninitialized pointer in attr_index_config()
Bug 630097 - (cov#11933) Fix NULL dereference in schema code
Bug 630097 - (cov#11938) NULL dereference in mmldif
Bug 630097 - (cov#11946) NULL dereference in ResHashCreate()
Bug 630097 - (cov#11964) Remove dead code from libaccess
Bug 630097 - (cov#12143) NULL dereference in cos cache code
Bug 630097 - (cov#12148) NULL dereference in ruvInit()
Bug 630097 - (cov#12182,12183) NULL dereference in import code
Bug 630097 - (cov#15460) NULL deference in ACL URL code
Bug 630097 - (cov#15461) Remove unnecessary NULL check in DNA
Bug 630097 - (cov#15462) NULL dereference in mep_modrdn_post_op()
Bug 630097 - (cov#15463) Remove NULL check in referint plugin
Bug 630097 - (cov#15464) NULL dereference in repl code
Bug 630097 - (cov#15465) Null dereference in USN code
Bug 630097 - (cov#15473) NULL dereference in ResHashCreate()
Bug 630097 - (cov#15505) NULL dereference in memberOf code
Bug 630097 - (cov#15506) NULL dereference in dblayer code
Bug 630097 - (cov#15507,15508) NULL dereference in entryrdn code
Bug 630097 - (cov#15509) NULL dereference in idsktune
Bug 630097 - (cov#11938) NULL dereference in mmldif
Bug 630097 - (cov#15477) NULL dereference in ACL plug-in code
Bug 630091 - (cov#12209) Use of uninitialized pointer in libaccess
Bug 630092 - (cov#12116) Resource leak in ldclt code
Bug 630092 - (cov#12105) Resource leak in pwdscheme config code
Bug 630092 - (cov#12068) Resource leak in certmap code
Bug 630091 - (cov#11973) Array overrun in libaccess
Bug 522055 - Scope check for managed attribute fails
Bug 625335 - Self-write aci has permission to invalid attribute
Bug 631993 - Log authzid when proxy auth control is used
Cov #16300 - Unused variable in account policy plugin
Bug 544321 - remove-ds.pl should not throw error unlabelling port
Bug 555955 - Allow CoS values to be merged
Bug 643937 - Initialize replication version flags
Bug 305131 - Allow empty modify operation
Bug 619633 - Make attribute uniqueness obey requiredObjectClass
Bug 619623 - attr-unique-plugin ignores requiredObjectClass on modrdn operations
Bug 189985 - Improve attribute uniqueness error message
Bug 647932 - multiple memberOf configuration adding memberOf where there is no member
Bug 521088 - DNA should check ACLs before getting a value from the range
Bug 635009 - Add one-way AD sync capability
Bump VERSION.sh to 1.2.8.a1
Bug 648949 - Move selinux policy into base OS
Bug 648949 - Update configure
Roll back VERSION.sh for 1.2.7 release
Bug 625950 - hash nsslapd-rootpw changes in audit log
Bug 656392 - Remove calls to ber_err_print()
Bug 656515 - Allow Name and Optional UID syntax for grouping attributes
Bug 197886 - Avoid overflow of UUID generator
Bug 658312 - Allow mapped attribute types to be quoted
Bug 197886 - Initialize return value for UUID generation code
Bug 658309 - Process escaped characters in managed entry mappings
Bug 659456 - Incorrect usage of ber_printf() in winsync code
Bug 641944 - Don't normalize non-DN RDN values
Bug 658312 - Invalid free in Managed Entry plug-in
Bug 661792 - Valid managed entry config rejected
Bug 588791 - Allow anonymous rootDSE access only
Bug 606439 - Creating server instance with LDAPI takes too long
Bug 632670 - Chain-on-update logs managed-entries-plugin errors
Bug 621008 - parsing purge RUV from changelog at startup fails
Bug 663191 - Don't use $USER in DSCreate.pm
Bug 663597 - Memory leaks in normalization code
Bug 659131 - Incorrect RDN values added with multi-valued RDN
Bug 661102 - Rename of managed entries not handled correctly
Bug 193297 - Call pre-bind plug-ins for all SASL bind steps
Bug 201652 - LDAPv2 bind with expired password doesn't unbind correctly
Bug 470576 - Migration could do addition checks before commiting actions
Bug 481195 - Missing op type in log when password change required
Bug 509897 - Validate dnaScope to ensure it is a legal DN
Bug 505722 - Allow ntGroup to have mail attribute present
Bug 543633 - replication problems if supplier is killed under update load
Bug 671033 - range sharing between server breaks with SASL/GSSAPI auth
Bug 527912 - setup-ds.pl appears to hang when DNS is unreachable
Bug 252249 - Add pkg-config file for plug-in developers
Bug 670616 - Allow SSF to be set for local (ldapi) connections
Bug 668862 - init scripts return wrong error code
Bug 674430 - Improve error messages for attribute uniqueness
Bug 675853 - dirsrv crash segfault in need_new_pw()
Bug 678646 - Ignore tombstone operations in managed entry plug-in
Bug 671199 - Don't allow other to write to rundir
Bug 672468 - Don't use empty path elements in LD_LIBRARY_PATH
Bug 674852 - crash in ldap-agent when using OpenLDAP
Bug 681345 - setup-ds.pl should set SuiteSpotGroup automatically
Bug 680558 - Winsync plugin fails to restrain itself to the configured subtree
Bug 504803 - Allow maxlogsize to be set if logmaxdiskspace is -1
Bug 687974 - (cov#10715) Fix Coverity uninitialized variables issues
Bug 688341 - (cov#10709) Fix Coverity code maintainability issues
Bug 688341 - (cov#10708) Fix Coverity code maintainability issues
Bug 688341 - (cov#10706,10707) Fix Coverity code maintainability issues
Bug 688341 - (cov#10704,10705) Fix Coverity code maintainability issues
Bug 688341 - (cov#10703) Fix Coverity code maintainability issues
Bug 688341 - (cov#10702) Fix Coverity code maintainability issues
Bug 688341 - (cov#10709) Fix Coverity code maintainability issues
Bug 689537 - (cov#10699) Fix Coverity NULL pointer dereferences
Bug 689537 - (cov#10610) Fix Coverity NULL pointer dereferences
Bug 689537 - (cov#10608) Fix Coverity NULL pointer dereferences
Bug 689952 - (cov#10581) Incorrect bit check in replication connection code
Bug 690526 - (cov#10734) Double free in dse_add()
Bug 690649 - (cov#10731) Use of free'd pointer in indexing code
Bug 690882 - (cov#10571) Incorrect sizeof use in uuid code
Bug 690882 - (cov#10636,10637) Useless comparison in attrcrypt
Bug 690882 - (cov#10703) Incorrect sizeof use in vattr code
Bug 690882 - (cov#10572,10710) Incorrect sizeof use in uuid code
Bug 691574 - (cov#10579) Check return value of ber_scanf() in sort code
Bug 691574 - (cov#10577) Check return types when adding RDN CSNs
Bug 691574 - (cov#10573) check return value in GER code
Bug 691574 - (cov#10575) Check return value of ldap_get_option
Bug 691574 - (cov#10573) Fix syntax error
Bug 693868 - Add managed entry config during in-place upgrade
Add Auto Membership Plug-in
Bug 698428 - Make auto membership use Slapi_DN for DN comparisons
Bug 695779 - windows sync can lose old values when a new value is added
Bug 700557 - Linked attrs callbacks access free'd pointers after close
Bug 700557 - Leak at shutdown in DNA plug-in
Bug 703304 - Auto membership alternate config area should override default area
Bug 703304 - Auto membership alternate config area should override default area
Bug 703530 - Allow Managed Entry config to be relocated
Bug 697961 - memberOf needs to be triggered by internal operations
Bug 710377 - Import with chain-on-update crashes ns-slapd
Split automember regex rules into separate entries
Bug 713209 - Update sudo schema
Bug 691313 - Need TLS/SSL error messages in repl status and errors log
Bug 723937 - Slapi_Counter API broken on 32-bit F15
Bug 725743 - Make memberOf use PRMonitor for it's operation lock
Bug 729717 - Fatal error messages when syncing deletes from AD
Bug 728510 - Run dirsync after sending updates to AD
Bug 730387 - Add slapi_rwlock API and use POSIX rwlocks
Bug 611438 - Add Account Usability Control support
Bug 728592 - Allow ns-slapd to start with an invalid server cert
Bug 732541 - Ignore error 32 when adding automember config
Bug 722292 - Entries in DS are not updated properly when using WinSync API
Bug 722292 - (cov#11030) Leak of mapped_sdn in winsync rename code
Bug 735114 - renaming a managed entry does not update mepmanagedby
Bug 739172 - Allow separate fractional attrs for incremental and total protocols
Bug 743966 - Compiler warnings in account usability plugin
Bug 744946 - (cov#11046) NULL dereference in IDL code
Bug 752155 - Use restorecon after creating init script lock file
Ticket 284 - Remove unnecessary SNMP MIB files
ticket 304 - Fix kernel version checking in dsktune
ticket 211 - Use of uninitialized variables in ldbm_back_modify()
ticket 181 - Allow PAM passthru plug-in to have multiple config entries
coverity 12563 Read from pointer after free (fix 2)
Ticket 211 - Avoid preop range requests non-DNA operations
Noriko Hosoi (326):
544089 - Referential Integrity Plugin does not take into account the attribute
557224 - subtree rename breaks the referential integrity plug-in
247413 - Incorrect error on multiple identical value add
559016 - Attempting to rename suffix returns inappropriate errors
555577 - Syntax validation fails for "ou=NetscapeRoot" tree
Undo - 555577 - Syntax validation fails for "ou=NetscapeRoot" tree
560827 - Admin Server templates: DistinguishName validation fails
548535 - memory leak in attrcrypt
563365 - Error handling problems in the backend functions
565664 - Incorrect parameter for CACHE_RETURN()
565987 - redhat-ds-base fails to build due to undefined struct
527848 - make sure db upgrade to 4.7 and later works correctly
539618 - Replication bulk import reports Invalid read/write
567370 - dncache: assertion failure in id2entry_delete
548115 - memory leak in schema reload
555970 - missing read lock in the combination of cos and nsview
539618 - Replication bulk import reports Invalid read/write
570667 - MMR: simultaneous total updates on the masters cause
Merge branch '547503'
Revert "Merge branch '547503'"
Bug 554573 - ACIs use bind DN from bind req rather than cert mapped DN from sasl/external
199923 - subtree search fails to find items under a db
570107 - The import of LDIFs with base-64 encoded DNs fails,
572649 - DS8.2 crashes on RHEL 4 (corresponding to bob, ber_2 test case)
573060 - DN normalizer: ESC HEX HEX is not normalized (
573896 - initializing subtree with invalid syntax crashes ns-slapd
515805 - Stop "initialize Database" crashes the server
548533 - memory leak in Repl_5_Inc_Protocol_new
Fixing a syntax error
Update to New DN Format
585905 - ACL with targattrfilters error crashes the server
574167 - An escaped space at the end of the RDN value is not
590931 - rhds81 import - hardcoded pages_limit for nsslapd-import-cache-autosize
591336 - Implementing upgrade DN format tool
593453 - Creating password policy with ns-newpolicy.pl on Replicated
593110 - backup-restore does not ALWAYS work
593899 - adding specific ACI causes very large mem allocate request
588867 - entryusn plugin fails on solaris
593899 - adding specific ACI causes very large mem allocate request
595893 - Base DN in SASL mapping is not normalized
511112 - Password history limited to 25 values
597375 - Deleting LDBM database causes backup/restore problem
574101 - MODRDN request never returns - possible deadlock
606920 - anonymous resource limit - nstimelimit -
605827 - In-place upgrade: upgrade dn format should not run in setup-ds-admin.pl
578296 - Attribute type entrydn needs to be added when subtree
609256 - Selinux: pwdhash fails if called via Admin Server CGI
609255 - fix coverity Defect Type: Memory - illegal accesses issues
609255 - fix coverity Defect Type: Memory - illegal accesses issues
609255 - fix coverity Defect Type: Memory - illegal accesses issues
609255 - fix coverity Defect Type: Memory - illegal accesses issues
609255 - fix coverity Defect Type: Memory - illegal accesses issues
609255 - fix coverity Defect Type: Memory - illegal accesses issues
609255 - fix coverity Defect Type: Memory - illegal accesses issues
609255 - fix coverity Defect Type: Memory - illegal accesses issues
609255 - fix coverity Defect Type: Memory - illegal accesses issues
609255 - fix coverity Defect Type: Memory - illegal accesses issues
609255 - fix coverity Defect Type: Memory - illegal accesses issues
609255 - fix coverity Defect Type: Memory - illegal accesses issues
609255 - fix coverity Defect Type: Memory - illegal accesses issues
609255 - fix coverity Defect Type: Memory - illegal accesses issues
609255 - fix coverity Defect Type: Memory - illegal accesses issues
609255 - fix coverity Defect Type: Memory - illegal accesses issues
616618 - 389 v1.2.5 accepts 2 identical entries with different DN formats
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
610281 - fix coverity Defect Type: Control flow issues
616608 - SIGBUS in RDN index reads on platforms with strict alignments
619595 - Upgrading sub suffix under non-normalized suffix disappears
513166 - Simple Paged result doesn't provide the server's estimate
621928 - Unable to enable replica (rdn problem?) on 1.2.6 rc6
Bug 194531 - db2bak is too noisy
Bug 622628 - fix coverity Defect Type: Integer handling issues
Bug 622628 - fix coverity Defect Type: Integer handling issues
Bug 622628 - fix coverity Defect Type: Integer handling issues
Bug 622903 - fix coverity Defect Type: Code maintainability issues
Bug 622903 - fix coverity Defect Type: Code maintainability issues
Bug 622903 - fix coverity Defect Type: Code maintainability issues
Bug 622903 - fix coverity Defect Type: Code maintainability issues
Bug 622903 - fix coverity Defect Type: Code maintainability issues
Bug 622903 - fix coverity Defect Type: Code maintainability issues
Bug 622903 - fix coverity Defect Type: Code maintainability issues
Bug 622903 - fix coverity Defect Type: Code maintainability issues
Bug 622903 - fix coverity Defect Type: Code maintainability issues
Bug 622903 - fix coverity Defect Type: Code maintainability issues
Bug 622903 - fix coverity Defect Type: Code maintainability issues
Bug 622903 - fix coverity Defect Type: Code maintainability issues
Bug 622903 - fix coverity Defect Type: Code maintainability issues
Bug 622903 - fix coverity Defect Type: Code maintainability issues
Bug 622903 - fix coverity Defect Type: Code maintainability issues
Bug 623118 - Simplepaged results going in infinite loop
Bug 614511 - fix coverity Defect Type: Null pointer dereferences issues 11846 - 11891
Bug 619122 - fix coverity Defect Type: Resource leaks issues CID 11975 - 12051
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 617630 - fix coverity Defect Type: Resource leaks issues CID 12052 - 12093
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 616500 - fix coverity Defect Type: Resource leaks issues CID 12094 - 12136
Bug 616500 - fix coverity Defect Type: Resource leaks issues CID 12094 - 12136
Bug 616500 - fix coverity Defect Type: Resource leaks issues CID 12094 - 12136
Bug 614511 - fix coverify Defect Type: Null pointer dereferences issues 11846 - 11891
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892 - 11939
Bug 613056 - fix coverify Defect Type: Null pointer dereferences issues 11892
Bug 616500 - fix coverity Defect Type: Resource leaks issues
Bug 623507 - fix coverity Defect Type: Incorrect expression issues
Bug 623507 - fix coverity Defect Type: Incorrect expression issues
Bug 613056 - fix coverify Defect Type: Null pointer dereferences
Bug 610119 - fix coverify Defect Type: Null pointer dereferences issues 12167 - 12199
Bug 610119 - fix coverify Defect Type: Null pointer dereferences issues 12167 - 12199
Bug 610119 - fix coverify Defect Type: Null pointer dereferences issues 12167 - 12199
Bug 610119 - fix coverify Defect Type: Null pointer dereferences issues 12167 - 12199
Bug 611790 - fix coverify Defect Type: Null pointer dereferences issues 11940 - 12166
Bug 611790 - fix coverify Defect Type: Null pointer dereferences issues 11940 - 12166
Bug 611790 - fix coverify Defect Type: Null pointer dereferences issues 11940 - 12166
Bug 611790 - fix coverify Defect Type: Null pointer dereferences issues 11940 - 12166
Bug 611790 - fix coverify Defect Type: Null pointer dereferences issues 11940 - 12166
Removed redundant code in agmt_new_from_entry
Bug 617630 - fix coverify Defect Type: Resource leaks issues CID 12052 - 12093
Bug 628300 - DN is not normalized in dn/entry cache when an entry is added, entrydn is not present in search results
Bug 531642 - EntryUSN: RFE: a configuration option to make entryusn "global"
Bug 627738 - The cn=monitor statistics entries for the dnentry cache do not change or change very rarely
DN normalizer should check the invalid type
Bug 627738 - The cn=monitor statistics entries for the dnentry cache
Bug 629710 - escape_string does not check '\<HEX><HEX>'
agmtlist_shutdown (repl5_agmtlist.c) had an illegal access defect.
Bug 633168 - Share backend dbEnv with the replication changelog
Bug 633168 - Share backend dbEnv with the replication changelog
Bug 631862 - crash - delete entries not in cache + referint
Bug 625014 - SubTree Renames: ModRDN operation fails and the server hangs if the entry is moved to "under" the same DN.
Bug 558099 - Enhancement request: Log more information about the search result being a paged one
Bug 635987 - Incorrect sub scope search result with
Bug 606920 - anonymous resource limit- nstimelimit -
Bug 635987 - Incorrect sub scope search result with ACL containing ldap:///self
Bug 639289 - Adding a new CN entry with UpperCase UTF-8 Character
Bug 640027 - Naming attribute with a special char sequence parsing bug
Bug 640854 - changelog db: _cl5WriteOperation: failed to
Bug 637852 - sasl_io_start_packet: failed - read only 3 bytes
Bug 586966 - Sample update script has syntax errors
Bug 586973 - Sample update ldif points to non-existent directory
Bug 602456 - Allow to add any cn=config attributes;
Bug 244229 - targetattr not verified against schema when setting an aci
Bug 643532 - Incorrect DNs sometimes returned on searches
Bug 592397 - Upgrade tool dn2rdn: it does not clean up
Bug 645061 - Upgrade: 06inetorgperson.ldif and 05rfc4524.ldif
Bug 629681 - Retro Changelog trimming does not behave as expected
Bug 644608 - RHDS 8.1->8.2 upgrade fails to properly migrate ACIs
Bug 644608 - RHDS 8.1->8.2 upgrade fails to properly migrate ACIs
Bug 644608 - RHDS 8.1->8.2 upgrade fails to properly migrate ACIs
Bug 638773 - permissions too loose on pid and lock files
Bug 491733 - dbtest crashes
Bug 329751 - "nested" filtered roles searches candidates more
Bug 567282 - server can not abandon searchRequest of "simple paged results"
Bug 572018 - Upgrading from 1.2.5 to 1.2.6.a2 deletes userRoot
Bug 651571 - When attrcrypt is on, entrydn is stored in the backend db
Bug 661918 - 389-ds MMR plugin's changelogdb path logic is incorrect
Bug 182507 - clear-password mod from replica is discarded before changelogged
Bug 602456 - Allow to add any cn=config attributes;
Bug 489379 - passwordExpirationTime in entry being added
Bug 663484 - Entry usn plugin fails to properly tag entries on initialization
Bug 664563 - GER: ger for non-present entry is not correct
Bug 653007 - db2ldif export of clear text passwords lacks storage scheme
Bug 667488 - Cannot recreate numsubordinates index with db2index
Bug 663752 - Cert renewal for attrcrypt and encchangelog
Bug 615100 - log rotationinfo always recreated at startup,
Bug 624442 - MMR: duplicate replica ID
Bug 669205 - db2bak: backed up changelog should include RUVs
Bug 616850 - ldapmodify failed to reject the replace operation
Bug 627993 - Inconsistent storage of password expiry times
Bug 627993 - Inconsistent storage of password expiry times
dn2rdn should respect the DB version info
Bug 646381 - Faulty password for nsmultiplexorcredentials does not give any error message in logs
Bug 624547 - attrcrypt should query the given slot/token for
Bug 668619 - slapd stops responding
Bug 151705 - Need to update Console Cipher Preferences with new ciphers
Bug 615052 - intrinsics and 64-bit atomics code fails to compile
Bug 616213 - insufficient stack size for HP-UX on PA-RISC
Bug 675265 - preventryusn gets added to entries on a failed delete
Bug 604881 - admin server log files have incorrect permissions/ownerships
Bug 676053 - export task followed by import task causes cache assertion
Bug 676053 - export task followed by import task causes cache assertion
Bug 676053 - export task followed by import task causes cache assertion
Bug 450016 - RFE- Console display values in KB/MB/GB
Cancelling commit aef19508c4f618285116d2068655183658f564d9
Bug 625424 - repl-monitor.pl doesn't work in hub node
Bug 679978 - modifying attr value crashes the server, which is supposed to
Bug 681015 - RFE: allow fine grained password policy duration attributes in days, hours, minutes, as well
Bug 668909 - Can't modify replication agreement in some cases
Bug 684996 - Exported tombstone cannot be imported correctly
Bug 681015 - RFE: allow fine grained password policy duration attributes in days, hours, minutes, as well
Bug 689866 - ns-newpwpolicy.pl needs to use the new DN format
Bug 690955 - Mrclone fails due to the replica generation id mismatch
Bug 696407 - If an entry with a mixed case RDN is turned to be
Bug 697027 - 1 - minor memory leaks found by Valgrind + TET
Bug 697027 - 2 - minor memory leaks found by Valgrind + TET
Bug 697027 - 3 - minor memory leaks found by Valgrind + TET
Bug 697027 - 4 - minor memory leaks found by Valgrind + TET
Bug 697027 - 5 - minor memory leaks found by Valgrind + TET
Bug 697027 - 6 - minor memory leaks found by Valgrind + TET
Bug 697027 - 7 - minor memory leaks found by Valgrind + TET
Bug 697027 - 8 - minor memory leaks found by Valgrind + TET
Bug 697027 - 9 - minor memory leaks found by Valgrind + TET
Bug 697027 - 10 - minor memory leaks found by Valgrind + TET
Bug 697027 - 11 - minor memory leaks found by Valgrind + TET
Bug 697027 - 12 - minor memory leaks found by Valgrind + TET
Bug 697027 - 13 - minor memory leaks found by Valgrind + TET
Bug 697027 - 14 - minor memory leaks found by Valgrind + TET
Bug 697027 - 15 - minor memory leaks found by Valgrind + TET
Bug 697027 - 16 - minor memory leaks found by Valgrind + TET
Bug 697027 - 3 - minor memory leaks found by Valgrind + TET
Bug 697027 - 3 - minor memory leaks found by Valgrind + TET
Bug 700215 - ldclt core dumps
Bug 668619 - slapd stops responding
Bug 709826 - Memory leak: when extra referrals configured
Bug 706179 - DS can not restart after create a new objectClass has entryusn attribute
Bug 663752 - Cert renewal for attrcrypt and encchangelog
Bug 663752 - Cert renewal for attrcrypt and encchangelog
Bug 711679 - unresponsive LDAP service when deleting vlv on replica
Bug 711679 - unresponsive LDAP service when deleting vlv on replica
Bug 718303 - Intensive updates on masters could break the consumer's cache
Merge branch '718303'
Bug 719069 - clean up compiler warnings in 389-ds-base 1.2.9
Bug 712855 - Directory Server 8.2 logs "Netscape Portable
Bug 663752 - Cert renewal for attrcrypt and encchangelog
Bug 732153 - subtree and user account lockout policies implemented?
Introducing an environment variable USE_VALGRIND to clean up the entry cache and dn cache on exit.
Bug 744945 - nsslapd-counters attribute value cannot be set to "off"
Keep unhashed password psuedo-attribute in the adding entry
Reduce the number of DN normalization
Bug 745259 - Incorrect entryUSN index under high load
Bug 750622 - Fix Coverity (11104) Resource leak:
Bug 750624 - Fix Coverity (11053) Explicit null dereferenced:
Bug 750625 - Fix Coverity (11066) Unused pointer value
Bug 750625 - Fix Coverity (11065) Uninitialized pointer read
Bug 750625 - Fix Coverity (11064) Dereference before null check
Bug 750625 - Fix Coverity (11061) Resource leak
Bug 750625 - Fix Coverity (11060) Dereference null return value
Bug 750625 - Fix Coverity (11058, 11059) Dereference null return value
Bug 750625 - Fix Coverity (11057) Dereference null return value
Bug 750625 - Fix Coverity (11055) Explicit null dereferenced
Bug 750625 - Fix Coverity (11054) Dereference after null check
Bug 750625 - Fix Coverity (11117) Uninitialized pointer read
Bug 750625 - Fix Coverity (11116) Uninitialized pointer read
Bug 750625 - Fix Coverity (11114, 11115) Uninitialized value use
Bug 750625 - Fix Coverity (11113) Uninitialized pointer read
Bug 750625 - Fix Coverity (11112) Uninitialized pointer read
Bug 750625 - Fix Coverity (11109, 11110, 11111) Uninitialized pointer read
Bug 750625 - Fix Coverity (11108) Sizeof not portable
Bug 750625 - Fix Coverity (11107) Dereference before null check
Bug 750625 - Fix Coverity (11096) Explicit null dereferenced
Bug 750625 - Fix Coverity (11095) Explicit null dereferenced
Bug 750625 - Fix Coverity (11094) Dereference after null check
Bug 750625 - Fix Coverity (11091) Unchecked return value
Bug 750625 - Fix Coverity (11055-2) Explicit null dereferenced
Bug 750625 - Fix Coverity (11062) Resource leak
Bug 750625 - Fix Coverity (11066-2) Unused pointer value
Bug 750625 - Fix Coverity (12195) Dereference after null check
Bug 750625 - Fix Coverity (12196) Dereference before null check
Bug 750625 - Fix Coverity (11066-3) Unused pointer value
Bug 745259 - Incorrect entryUSN index under high load in
Trac Ticket 2 - If node entries are tombstone'd,
Trac Ticket 2 - If node entries are tombstone'd,
Trac Ticket 26 - Please support setting
Trac Ticket 75 - Unconfigure plugin opperations are being called.
Trac Ticket 168 - minssf should not apply to rootdse
Trac Ticket #18 - Data inconsitency during replication
Trac Ticket #52 - FQDN set to nsslapd-listenhost
Trac Ticket 139 - eliminate the use of char *dn in favor of Slapi_DN *dn
Trac Ticket 35 - Log not clear enough on schema errors
Trac Ticket #274 - Reindexing entryrdn fails if
Trac Ticket #275 - Invalid read reported by valgrind
Trac Ticket 51 - memory leaks in 389-ds-base-1.2.8.2-1.el5?
Trac Ticket #27 - SASL/PLAIN binds do not work
Trac Ticket #84 - 389 Directory Server Unnecessary Checkpoints
Trac Ticket #169 - allow 389 to use db5
Trac Ticket #34 - remove-ds.pl does not remove everything
Trac Ticket #26 - Please support setting defaultNamingContext in the rootdse.
Trac Ticket #298 - crash when replicating orphaned tombstone entry
Trac Ticket #290 - server hangs during shutdown if betxn pre/post op fails
Trac Ticket #290 - server hangs during shutdown if betxn pre/post op fails
Minor bug fix introcuded by commit 69c9f3bf7dd9fe2cadd5eae0ab72ce218b78820e
Trac Ticket #260 - 389 DS does not support multiple
Fixing compiler warnings
Trac Ticket #303 - make DNA range requests work with transactions
coverity 12606 Logically dead code
Trac Ticket #46 - setup-ds-admin.pl does not like ipv6 only hostnames
Trac Ticket #46 (revised) - setup-ds-admin.pl does not like ipv6 only hostnames
Trac Ticket #46 - (take 3) setup-ds-admin.pl does not like ipv6 only hostnames
Trac Ticket #46 - (additional) setup-ds-admin.pl does not
Trac Ticket #45 - Fine Grained Password policy:
Trac Ticket #46 - (additional 2) setup-ds-admin.pl does not like ipv6 only hostnames
Trac Ticket #335 - transaction retries need to be cache aware
Trac Ticket #338 - letters in object's cn get converted to
Trac Ticket #310 - Avoid calling escape_string() for logged DNs
Trac Ticket #19 - Convert entryUSN plugin to transaction aware type
Trac Ticket #345 - db deadlock return should not log error
Trac Ticket #359 - Database RUV could mismatch the one
Trac Ticket #338 - letters in object's cn get converted to
Trac Ticket #359 - Database RUV could mismatch the one
Rich Megginson (347):
Net::LDAP password modify extop breaks; msgid in response is 0xFF
Clean up assert for entrydn
Bug 543080 - Bitwise plugin fails to return the exact matched entries for Bitwise search filter
Bug 537466 - nsslapd-distribution-plugin should not require plugin name to begin with "lib"
bump version to 1.2.6.a2
Do not use syntax plugins directly for filters, indexing
wrap new style matching rule plugins for use in old style indexing code
change extensible filter code to use new syntax function style mr funcs
change syntax plugins to register required matching rule plugins
crash looking up compat syntax; numeric string syntax using integer; make octet string ordering work correctly
fix memory leak in attr replace when replacement fails
fix dso linking issues found by fedora 13 linking
problems linking with -z defs
389 DS segfaults on libsyntax-plugin.so - part 1
389 DS segfaults on libsyntax-plugin.so - part 2
389 DS segfaults on libsyntax-plugin.so - part 3
Bug 460162 - FedoraDS "with-FHS" installs init.d StartupScript in wrong location on non-RHEL/Fedora OS
Bug 568196 - Install DS8.2 on Solaris fails
Bug 568196 - Install DS8.2 on Solaris fails - part 2
Bug 551198 - LDAPI: incorrect logging to access log
bump version to 1.2.6.a3
fix various memory leaks
Bug 551198 - LDAPI: incorrect logging to access log - part 2
Bug 554573 - ACIs use bind DN from bind req rather than cert mapped DN from sasl/external
cleanup build warnings
Bug 571514 - upgrade to 1.2.6 should upgrade 05rfc4523.ldif (cert schema)
Bug 570905 - postalAddress syntax should allow empty lines (should allow $$)
Add support for additional schema/matching rules included with 389
Bug 572677 - Memory leak in searches including GER control
Bug 571677 - Busy replica on consumers when directly deleting a replication conflict
Bug 576074 - search filters with parentheses fail
Bug 567429 - slapd didn't close connection and get into CLOSE_WAIT state
Bug 578167 - repl. of mod/replace deletes multi-valued attrs
Bug 561575 - setup-ds-admin fails to supply nsds5ReplicaName when configuring via ConfigFile
Bug 572162 - the string "|*" within a search filter on a non-indexed attribute returns all elements.
Bug 576644 - segfault while multimaster replication (paired node won't find deleted entries)
start of 1.2.6.a4
Bug 572018 - Upgrading from 1.2.5 to 1.2.6.a2 deletes userRoot
Fix too few args for format warning in acllas
Bug 586571 - DS Console shows escaped DNs
Bug 591685 - Server instances Fail to Start on Solaris due to Library Path and pcre
bump console version to 1.2.3
Repl Session API needs to check for NULL api before init
Bug 593392 - setup-ds-admin.pl -k creates world readable file
Bug 595874 - 99user.ldif getting overpopulated
bump version to 1.2.6.a5
bump version to 1.2.6.rc1
bump version to 1.2.6.rc2
bump version to 1.2.6.rc3
Bug 604453 - SASL Stress and Server crash: Program quits with the assertion failure in PR_Poll
Bug 604453 - SASL Stress and Server crash: Program quits with the assertion failure in PR_Poll
Bug 603942 - null deref in _ger_parse_control() for subjectdn
bump version to 1.2.6.rc4
Bug 609590 - fix coverity Defect Type: Memory - corruptions issues
Bug 609590 - fix coverity Defect Type: Memory - corruptions issues
Bug 609590 - fix coverity Defect Type: Memory - corruptions issues
Bug 609590 - fix coverity Defect Type: Memory - corruptions issues
Bug 609590 - fix coverity Defect Type: Memory - corruptions issues
Bug 609590 - fix coverity Defect Type: Memory - corruptions issues
Bug 609590 - fix coverity Defect Type: Memory - corruptions issues
Bug 609590 - fix coverity Defect Type: Memory - corruptions issues
Bug 609590 - fix coverity Defect Type: Memory - corruptions issues
Bug 602530 - coverity: op_shared_modify: compare pre, post and original entries before freeing them
Bug 602531 - coverity: op_shared_delete: compare preop entry and GLUE_PARENT_ENTRY before freeing them
Bug 609590 - fix coverity Defect Type: Memory - corruptions issues
Bug 610177 - fix coverity Defect Type: Uninitialized variables issues
Bug 610276 - fix coverity Defect Type: API usage errors issues
Bug 611850 - fix coverity Defect Type: Error handling issues
Bug 614242 - C99/ANSI C++ related compile errors on HP-UX
Bug 547503 - replication broken again, with 389 MMR replication and TCP errors
Bug 617013 - repl-monitor.pl use cpu upto 90%
fix build failures due to libtool problems
Bug 617629 - Missing aliases in new schema files
Bug 617862 - Replication: Unable to delete tombstone errors
bump version to 1.2.7.a1
Bug 610281 - fix coverity Defect Type: Control flow issues - daemon.c:write_function()
Bug 610281 - fix coverity Defect Type: Control flow issues - last repl init status
postalAddress syntax does not accept empty values
ger should support both "dn" and "distinguishedName"
openldap - ldap_url_parse_ext is not part of the public api
fix memleak in ldbm_config_read_instance_entries
Add -x option to ldap tools when using openldap
openldap - add support for missing controls, add ldif api, fix NSS usage
port client tools to use openldap API
use the mozldap versions of the proxy auth control create function
document slapi wrappers for openldap/mozldap functions that differ
fix some compiler warnings
use strcasecmp with ptype and type->bv_val
ber_printf 'o' cannot handle NULL bv_val
fix the url_parse logic when looking for a missing suffix DN
openldap ldapsearch uses -LLL to suppress # version: N
add ldaptool_opts for the non BUNDLE case in Makefile.am
openldap ldapsearch returns empty line at end of LDIF output
have to use LDAP_OPT_X_TLS_NEVER to defeat cert hostname checking
openldap_read_function needs to set EWOULDBLOCK if the buffer is empty
do not terminate unwrapped LDIF line with another newline
slapi_ldap_url_parse must handle multiple host:port in url
convert mozldap host list to openldap uri list
move the out pointer back if continuation lines were removed
check src < *out only; only check for \nspace if src < *out - 2
use slapi_ldap_url_parse in the acl code
do not un-null-terminate normalized DN until new url is constructed
implement slapi_ldap_explode_dn and slapi_ldap_explode_rdn
use slapi_pblock_set to set the ldap result code for the be postop plugins
pass the string copy to slapi_dn_normalize_original
bug 614511 - fix coverity null reference - revert macro aci $dn logic
fix compiler warnings - unused vars/funcs, invalid casts
use slapi_mods_init_passin/get_ldapmods_passout if modifying the smods
Have to explicitly set protocol version to 3
Only check modrdn ops for backend/suffix correctness if not the default backend
Bug 634561 - Server crushes when using Windows Sync Agreement
openldap ber_init will assert if the bv->bv_val is NULL
add the account policy plugin and related server code, schema, and config
fix pblock memory leak
do not register pre/post op plugins if disabled
add support for global inactivity limit
fix typos in Makefile.am, acctpolicy schema
bump version to 1.2.7.a2
remove extra format argument; use %lu for size_t printf format
Bug 644013 - uniqueness plugin segfault bug
bump version to 1.2.7.a3
bump to 1.2.7.a4
bump version to 1.2.7.a5
put replication config entries in separate file
bump version to 1.2.7.a6
bump version to 1.2.7.1
bump version to 1.2.7.2
bump version to 1.2.7.3
bump version to 1.2.7.4
Bug 515329 - Multiple mods in one operation can result in an inconsistent replica
bump version to 1.2.8.a1
Bug 642046 - Segfault when using SASL/GSSAPI multimaster replication, possible krb5_creds doublefree
Bug 624485 - setup dsktune check step should default to "yes" if no problems found
Bug 622907 - support piped passwords to perl-based maintenance commands
Bug 624485 - setup dsktune check step should default to "yes" if no problems found
Bug 576534 - Password displayed on console when entered in command-line utilities
Bug 667935 - DS pipe log script's logregex.py plugin is not redirecting the log output to the text file
bump version to 1.2.8.a2
Bug 668385 - DS pipe log script is executed as many times as the dirsrv service is restarted
Bug 676689 - crash while adding a new user to be synced to windows
Bug 675113 - ns-slapd core dump in windows_tot_run if oneway sync is used
Bug 677440 - clean up compiler warnings in 389-ds-base 1.2.8
Bug 677774 - DS fails to start after reboot
Bug 666076 - dirsrv crash (1.2.7.5) with multiple simple paged result searches
Bug 675320 - empty modify operation with repl on or lastmod off will crash server
bump version to 1.2.9.a1 - console version to 1.2.4
Bug 677705 - ds-logpipe.py script is failing to validate "-s" and "--serverpid" options with "-t".
Bug 676655 - winsync stops working after server restart
Bug 680555 - ns-slapd segfaults if I have more than 100 DBs
Bug 514190 - setup-ds-admin.pl --debug does not log to file
Bug 518890 - setup-ds-admin.pl - improve hostname validation
Bug 644784 - Memory leak in "testbind.c" plugin
Bug 683250 - slapd crashing when traffic replayed
Bug 690584 - #10691 ldbm_back_init() - fix coverity resource leak issues
Bug 690584 - #10690 #10689 attrcrypt_get_ssl_cert_name() - fix coverity resource leak issues
Bug 690584 - #10688 - dblayer_make_env - fix coverity resource leak issues
Bug 690584 - #10669 #10668 cl5ImportLDIF - fix coverity resource leak issues
Bug 690584 - #10658 linked_attrs_pre_op - fix coverity resource leak issues
Bug 690584 - #10655 acllas__handle_group_entry - fix coverity resource leak issues
Bug 690584 - #10654 #10653 str2entry_dupcheck - fix coverity resource leak issues
Bug 690584 - #10652 #10651 #10650 #10649 #10648 #10647 send_specific_attrs send_all_attrs - fix coverity resource leak issues
Bug 690584 - #10643 hash_rootpw - fix coverity resource leak issues
Bug 690584 - #10641 reslimit_bv2int - fix coverity resource leak issues
Bug 691422 - sdt_destroy - fix coverity control flow issues
Bug 691422 - ldbm_back_upgradedb - fix coverity control flow issues
Bug 691422 - csnplFree - fix coverity control flow issues
Bug 691422 - SetUnicodeStringFromUTF_8 - fix coverity control flow issues
Bug 691422 - cl5DeleteRUV - fix coverity control flow issues
Bug 691422 - acl_read_access_allowed_on_entry - fix coverity control flow issues
Bug 691422 - search_internal_callback_pb - fix coverity control flow issues
Bug 691422 - cl5WriteRUV - fix coverity control flow issues
Bug 691422 - windows_replay_update - fix coverity control flow issues
Bug 690584 - #10691 ldbm_back_init() - fix coverity resource leak issues
Bug 690584 - #10652 #10651 #10650 #10649 #10648 #10647 send_specific_attrs send_all_attrs - fix coverity resource leak issues
Bug 668385 - DS pipe log script is executed as many times as the dirsrv service is restarted
Bug 692937 - Replica install fails after step for "enable GSSAPI for replication"
Bug 692331 - Segfault on index update during full replication push on 1.2.7.5
Bug 693451 - cannot use localized matching rules
Bug 693455 - nsMatchingRule does not work with multiple values
Bug 693503 - matching rules do not inherit from superior attribute type
Bug 693466 - Unable to change schema online
Bug 692991 - rhds82 - windows_tot_run: failed to obtain data to send to the consumer; LDAP error - -1
Bug 693473 - rhds82 rfe - windows_tot_run to log Sizelimit exceeded instead of LDAP error - -1
Bug 693962 - Full replica push loses some entries with multi-valued RDNs
Bug 694336 - Group sync hangs Windows initial Sync
Bug 700145 - userpasswd not replicating
Bug 703990 - Support upgrade from Red Hat Directory Server
bump console version to 1.2.5
Bug 703990 - Support upgrade from Red Hat Directory Server
Bug 703990 - Support upgrade from Red Hat Directory Server
Bug 707015 - Cannot disable SSLv3 and use TLS only
bump version to 1.2.9.a2
Bug 707384 - only allow FIPS approved cipher suites in FIPS mode
Bug 711906 - ns-slapd segfaults using suffix referrals
Bug 706209 - LEGAL: RHEL6.1 License issue for 389-ds-base package
Bug 703703 - setup-ds-admin.pl asks for legal agreement to a non-existant file
Bug 711679 - unresponsive LDAP service when deleting vlv on replica
bump console version to 1.2.6
Bug 697694 - rhds82 - incr update state stop_fatal_error "requires administrator action", with extop_result: 9
Bug 716980 - winsync uses old AD entry if new one not found
add support for ldif files with changetype: add
writing Inf file shows SchemaFile = ARRAY(0xhexnum)
look for separate openldap ldif library
bump version to 1.2.9.a3
Bug 709468 - RSA Authentication Server timeouts when using simple paged results on RHDS 8.2.
Bug 720059 - RDN with % can cause crashes or missing entries
bump version to 1.2.9.0
Bug 725542 - Instance upgrade fails when upgrading 389-ds-base package
Bug 725953 - Winsync: DS entries fail to sync to AD, if the User's CN entry contains a comma
Bug 723937 - replication failing on RUV errors
bump version to 1.2.9.1
Bug 727511 - ldclt SSL search requests are failing with "illegal error number -1" error
bump version to 1.2.9.2
Bug 727511 - ldclt SSL search requests are failing with "illegal error numbe
bump version to 1.2.9.3
Bug 727511 - ldclt SSL search requests are failing with "illegal error number -1" error
bump version to 1.2.9.4
Bug 727511 - ldclt SSL search requests are failing with "illegal error number -1" error
bump version to 1.2.9.5
Bug 729378 - delete user subtree container in AD + modify password in DS == DS crash
Bug 723937 - replication failing on RUV errors
Bug 729369 - upgrade DB to upgrade from entrydn to entryrdn format is not working.
make sure the DBVERSION file ends in a newline
bump version to 1.2.10.a1
Bug 633803 - passwordisglobalpolicy attribute brakes TLS chaining
Bug 733103 - large targetattr list with syntax errors cause server to crash or hang
Bug 703990 - cross-platform - Support upgrade from Red Hat Directory Server
Bug 735121 - simple paged search + ip/dns based ACI hangs server
Bug 695736 - Providing native systemd file for upcoming F15 Feature Systemd
Bug 590826 - Reloading database from ldif causes changelog to emit "data no longer matches" errors
Bug 736712 - Modifying ruv entry deadlocks server
Add support for pre/post db transaction plugins
Make all backend operations transaction aware
Bug 741744 - MOD operations with chained delete/add get back error 53 on backend config
Bug 742324 - allow nsslapd-idlistscanlimit to be set dynamically and per-user
Bug 741744 - part2 - MOD operations with chained delete/add get back error 53 on backend config
Bug 740942 - allow resource limits to be set for paged searches independently of limits for other searches/operations
bump version to 1.2.10.a2
bump version to 1.2.10.a3
fix transaction support in ldbm_delete
bump version to 1.2.10.a4
set the ENTRY_POST_OP for modrdn betxnpostoperation plugins
pass the plugin config entry to the plugin init function
make memberof transaction aware and able to be a betxnpostoperation plugin
Bug 741744 - part3 - MOD operations with chained delete/add get back error 53
bump version to 1.2.10.a5
Change referential integrity to be a betxnpostoperation plugin
Use new PLUGIN_CONFIG_ENTRY feature to allow switching between txn and regular
Bug 748575 - rhds81 modrn operation and 100% cpu use in replication
Bug 748575 - part 2 - rhds81 modrdn operation and 100% cpu use in replication
Bug 751495 - 'setup-ds.pl -u' fails with undefined routine 'updateSystemD'
bump version to 1.2.10.a6
Bug 751645 - crash when simple paged fails to send entry to client
csn_as_string - use slapi_uN_to_hex instead of sprintf
uniqueid formatting - use slapi_u8_to_hex instead of sprintf
fix member variable name error in slapi_uniqueIDFormat
reduce calls to csn_as_string and slapi_log_error
csn_init_as_string should not use sscanf
use slapi_hexchar2int and slapi_str_to_u8 everywhere
Bug 755754 - Unable to start dirsrv service using systemd
Bug 755725 - 389 programs linked against openldap crash during shutdown
Ticket 1 - pre-normalize filter and pre-compile substring regex - and other optimizations
Ticket #162 - Infinite loop / spin inside strcmpi_fast, acl_read_access_allowed_on_attr, server DoS
bak2db gets stuck in infinite loop
Ticket #256 - debug build assertion in ACL_EvalDestroy()
bump version to 1.2.10.a7
Ticket #167 - Mixing transaction and non-transaction plugins can cause deadlock
fix mep sdn compiler warnings
add a hack to disable sasl hostname canonicalization - helps with testing when you don't want to set up correct host name resolution and/or cannot set the default system hostname
Ticket #12 - 389 DS DNA Plugin / Replication failing on GSSAPI
Ticket #257 - repl-monitor doesn't work if leftmost hostnames are the same
fix recent compiler warnings
Ticket #15 - Get rid of rwlock.h/rwlock.c and just use slapi_rwlock instead
fix compiler warnings
Remove redundant code - make a global into a static
Ticket #262 - pid file not removed with systemd
fix mozldap build issues
Ticket #264 - upgrade needs better check for "server is running"
Ticket #263 - add systemd include directive
bump version to 1.2.10.rc1
change version to 1.2.10.a8
Ticket #272 - add tombstonenumsubordinates to schema
bump version to 1.2.10.rc1
Ticket #161 - Review and address latest Coverity issues
Ticket #22 - RFE: Support sendmail LDAP routing schema
Ticket #29 - Samba3-schema is missing sambaTrustedDomainPassword
Ticket #273 - ruv tombstone searches don't work after reindex entryrdn
Ticket #273 - ruv tombstone searches don't work after reindex entryrdn
fix a couple of minor coverity issues
Ticket #87 - Manpages fixes
Ticket #13 - slapd process exits when put the database on read only mode while updates are coming to the server
Ticket #55 - Limit of 1024 characters for nsMatchingRule
Ticket #277 - cannot set repl referrals or state
Ticket #278 - Schema replication update failed: Invalid syntax
Ticket #277 - cannot set repl referrals or state
Ticket #279 - filter normalization does not use matching rules
Ticket #280 - extensible binary filters do not work
Ticket #281 - TLS not working with latest openldap
coverity 12488 Resource leak In attr_index_config(): Leak of memory or pointers to system resources
bump version to 1.2.10.rc2
fix compiler warning in acct policy plugin
bump version to 1.2.11.a1
Ticket #294 - 389 DS Segfaults during replica install in FreeIPA
coverity uninit var and resource leak
Revert "Ticket #111 - ability to control behavior of modifyTimestamp/modifiersName"
Revert "Ticket #167 - Mixing transaction and non-transaction plugins can cause deadlock"
Revert "Change referential integrity to be a betxnpostoperation plugin"
Revert "make memberof transaction aware and able to be a betxnpostoperation plugin"
Revert "pass the plugin config entry to the plugin init function"
coverity 12559 Uninitialized pointer read In ldbm_back_modify(): Reads an uninitialized pointer or its target
Ticket #281 - TLS not working with latest openldap
Trac Ticket #298 - crash when replicating orphaned tombstone entry
Ticket #301 - implement transaction support using thread local storage
init txn thread private data for all database modes
handle null smods
memleak in mep_parse_config_entry
memleak in normalize_mods2bvals
destroy the entry cache and dn cache in the dse post op delete callback
Ticket #289 - allow betxn plugin config changes
coverity 12563 Read from pointer after free
Ticket 317 - RHDS fractional replication with excluded password policy attributes leads to wrong error messages.
Ticket #305 - Certain CMP operations hang or cause ns-slapd to crash
Ticket #320 - allow most plugins to be betxn plugins
Ticket #324 - Sync with group attribute containing () fails
Ticket #324 - redux: Sync with group attribute containing () fails
Ticket #316 and Ticket #70 - add post add/mod and AD add callback hooks
Ticket #261 - Add Solaris i386
Ticket #331 - transaction errors with db 4.3 and db 4.2
schema def must have DESC '' - close paren must be preceded by space
Ticket #336 - [abrt] 389-ds-base-1.2.10.4-2.fc16: index_range_read_ext: Process /usr/sbin/ns-slapd was killed by signal 11 (SIGSEGV)
Ticket #336 - [abrt] 389-ds-base-1.2.10.4-2.fc16: index_range_read_ext: Process /usr/sbin/ns-slapd was killed by signal 11 (SIGSEGV)
Ticket #347 - IPA dirsvr seg-fault during system longevity test
Ticket #348 - crash in ldap_initialize with multiple threads
Ticket #351 - use betxn plugins by default
Ticket #353 - coverity 12625-12629 - leaks, dead code, unchecked return
bump version to 1.2.11.1
Ticket #348 - crash in ldap_initialize with multiple threads
Ticket #351 - use betxn plugins by default
bump version to 1.2.11.2
Ticket #358 - managed entry doesn't delete linked entry
bump version to 1.2.11.3
Trac Ticket #359 - Database RUV could mismatch the one in changelog under the stress
Ticket #321 - krbExtraData is being null modified and replicated on each ssh login
Ticket #360 - ldapmodify returns Operations error
Ticket #382 - DS Shuts down intermittently
Ticket #383 - usn + mmr = deletions are not replicated
bump version to 1.2.11.4
nturpin (1):
Ticket #3: acl cache overflown problem
root (4):
Bug 480787 - Autoconf parameter --with and --without
Ticket #326 - MemberOf plugin should work on all backends
Ticket #337 - RFE - Improve CLEANRUV functionality
Ticket #216 - RFE - Disable replication agreements
---
.gitignore | 1
Makefile.am | 267
Makefile.in | 5258 -
README | 11
VERSION.sh | 7
aclocal.m4 | 6996 --
compile | 21
config.guess | 302
config.h.in | 25
config.sub | 232
configure |41959 +++++-------
configure.ac | 196
depcomp | 172
dirsrv.pc.in | 7
include/base/dbtbase.h | 2
include/base/file.h | 3
include/base/lexer.h | 126
include/base/rwlock.h | 91
include/i18n.h | 115
include/ldaputil/ldaputil.h | 10
include/libaccess/aclerror.h | 1
include/libaccess/aclproto.h | 15
include/libaccess/aclstruct.h | 2
include/libaccess/dbtlibaccess.h | 3
include/public/nsacl/aclapi.h | 7
install-sh | 517
ldap/admin/src/base-initconfig.in | 44
ldap/admin/src/initconfig.in | 37
ldap/admin/src/logconv.pl | 809
ldap/admin/src/scripts/10cleanupldapi.pl | 23
ldap/admin/src/scripts/10fixrundir.pl | 11
ldap/admin/src/scripts/50acctusabilityplugin.ldif | 21
ldap/admin/src/scripts/50automemberplugin.ldif | 15
ldap/admin/src/scripts/50fixNsState.pl | 240
ldap/admin/src/scripts/50managedentriesplugin.ldif | 16
ldap/admin/src/scripts/50refintprecedence.ldif | 4
ldap/admin/src/scripts/50smd5pwdstorageplugin.ldif | 5
ldap/admin/src/scripts/60upgradeschemafiles.pl | 2
ldap/admin/src/scripts/70upgradefromldif.pl | 108
ldap/admin/src/scripts/80upgradednformat.pl | 206
ldap/admin/src/scripts/81changelog.pl | 34
ldap/admin/src/scripts/90subtreerename.pl | 21
ldap/admin/src/scripts/91subtreereindex.pl | 148
ldap/admin/src/scripts/DSCreate.pm.in | 338
ldap/admin/src/scripts/DSDialogs.pm | 6
ldap/admin/src/scripts/DSMigration.pm.in | 47
ldap/admin/src/scripts/DSUpdate.pm.in | 50
ldap/admin/src/scripts/DSUtil.pm.in | 329
ldap/admin/src/scripts/DialogManager.pm | 241
ldap/admin/src/scripts/DialogManager.pm.in | 241
ldap/admin/src/scripts/Inf.pm | 67
ldap/admin/src/scripts/Migration.pm.in | 20
ldap/admin/src/scripts/Setup.pm.in | 20
ldap/admin/src/scripts/SetupDialogs.pm.in | 31
ldap/admin/src/scripts/SetupLog.pm | 8
ldap/admin/src/scripts/dnaplugindepends.ldif | 3
ldap/admin/src/scripts/ds-logpipe.py | 221
ldap/admin/src/scripts/exampleupdate.ldif | 2
ldap/admin/src/scripts/exampleupdate.sh | 10
ldap/admin/src/scripts/logregex.py | 16
ldap/admin/src/scripts/migrate-ds.pl.in | 13
ldap/admin/src/scripts/remove-ds.pl.in | 30
ldap/admin/src/scripts/repl-monitor.pl.in | 86
ldap/admin/src/scripts/restart-dirsrv.in | 25
ldap/admin/src/scripts/setup-ds.pl.in | 7
ldap/admin/src/scripts/setup-ds.res.in | 35
ldap/admin/src/scripts/start-dirsrv.in | 43
ldap/admin/src/scripts/stop-dirsrv.in | 27
ldap/admin/src/scripts/template-bak2db.in | 49
ldap/admin/src/scripts/template-bak2db.pl.in | 29
ldap/admin/src/scripts/template-db2bak.in | 53
ldap/admin/src/scripts/template-db2bak.pl.in | 29
ldap/admin/src/scripts/template-db2index.in | 14
ldap/admin/src/scripts/template-db2index.pl.in | 33
ldap/admin/src/scripts/template-db2ldif.in | 15
ldap/admin/src/scripts/template-db2ldif.pl.in | 29
ldap/admin/src/scripts/template-dbverify.in | 15
ldap/admin/src/scripts/template-dn2rdn.in | 25
ldap/admin/src/scripts/template-fixup-linkedattrs.pl.in | 29
ldap/admin/src/scripts/template-fixup-memberof.pl.in | 29
ldap/admin/src/scripts/template-ldif2db.in | 15
ldap/admin/src/scripts/template-ldif2db.pl.in | 29
ldap/admin/src/scripts/template-ldif2ldap.in | 19
ldap/admin/src/scripts/template-monitor.in | 19
ldap/admin/src/scripts/template-ns-accountstatus.pl.in | 33
ldap/admin/src/scripts/template-ns-activate.pl.in | 33
ldap/admin/src/scripts/template-ns-inactivate.pl.in | 33
ldap/admin/src/scripts/template-ns-newpwpolicy.pl.in | 47
ldap/admin/src/scripts/template-restart-slapd.in | 2
ldap/admin/src/scripts/template-restoreconfig.in | 15
ldap/admin/src/scripts/template-saveconfig.in | 15
ldap/admin/src/scripts/template-schema-reload.pl.in | 29
ldap/admin/src/scripts/template-start-slapd.in | 3
ldap/admin/src/scripts/template-stop-slapd.in | 2
ldap/admin/src/scripts/template-suffix2instance.in | 15
ldap/admin/src/scripts/template-syntax-validate.pl.in | 29
ldap/admin/src/scripts/template-upgradedb.in | 15
ldap/admin/src/scripts/template-upgradednformat.in | 63
ldap/admin/src/scripts/template-usn-tombstone-cleanup.pl.in | 29
ldap/admin/src/scripts/template-verify-db.pl.in | 19
ldap/admin/src/scripts/template-vlvindex.in | 15
ldap/admin/src/slapd.inf.in | 2
ldap/admin/src/template-initconfig.in | 18
ldap/docs/LICENSE.txt | 132
ldap/docs/README.txt | 11
ldap/include/ldaplog.h | 32
ldap/ldif/50replication-plugins.ldif | 26
ldap/ldif/template-baseacis.ldif.in | 2
ldap/ldif/template-bitwise.ldif.in | 6
ldap/ldif/template-dnaplugin.ldif.in | 2
ldap/ldif/template-dse.ldif.in | 96
ldap/ldif/template-suffix-db.ldif.in | 1
ldap/schema/00core.ldif | 72
ldap/schema/01core389.ldif | 27
ldap/schema/02common.ldif | 12
ldap/schema/05rfc4523.ldif | 14
ldap/schema/05rfc4524.ldif | 30
ldap/schema/06inetorgperson.ldif | 5
ldap/schema/10automember-plugin.ldif | 123
ldap/schema/10dna-plugin.ldif | 204
ldap/schema/10mep-plugin.ldif | 104
ldap/schema/30ns-common.ldif | 4
ldap/schema/50ns-directory.ldif | 4
ldap/schema/60acctpolicy.ldif | 47
ldap/schema/60nis.ldif | 2
ldap/schema/60pam-plugin.ldif | 3
ldap/schema/60qmail.ldif | 24
ldap/schema/60sabayon.ldif | 10
ldap/schema/60samba3.ldif | 34
ldap/schema/60sendmail.ldif | 54
ldap/schema/60sudo.ldif | 58
ldap/servers/plugins/acct_usability/acct_usability.c | 464
ldap/servers/plugins/acct_usability/acct_usability.h | 63
ldap/servers/plugins/acctpolicy/acct_config.c | 143
ldap/servers/plugins/acctpolicy/acct_init.c | 191
ldap/servers/plugins/acctpolicy/acct_plugin.c | 313
ldap/servers/plugins/acctpolicy/acct_util.c | 257
ldap/servers/plugins/acctpolicy/acctpolicy.h | 81
ldap/servers/plugins/acctpolicy/sampleconfig.ldif | 40
ldap/servers/plugins/acctpolicy/samplepolicy.ldif | 27
ldap/servers/plugins/acl/acl.c | 247
ldap/servers/plugins/acl/acl.h | 43
ldap/servers/plugins/acl/acl_ext.c | 152
ldap/servers/plugins/acl/aclanom.c | 24
ldap/servers/plugins/acl/acleffectiverights.c | 116
ldap/servers/plugins/acl/aclgroup.c | 19
ldap/servers/plugins/acl/aclinit.c | 2
ldap/servers/plugins/acl/acllas.c | 402
ldap/servers/plugins/acl/acllist.c | 79
ldap/servers/plugins/acl/aclparse.c | 615
ldap/servers/plugins/acl/aclplugin.c | 37
ldap/servers/plugins/acl/aclproxy.c | 232
ldap/servers/plugins/acl/aclutil.c | 117
ldap/servers/plugins/automember/automember.c | 2651
ldap/servers/plugins/automember/automember.h | 134
ldap/servers/plugins/bitwise/bitwise.c | 23
ldap/servers/plugins/chainingdb/cb.h | 8
ldap/servers/plugins/chainingdb/cb_add.c | 105
ldap/servers/plugins/chainingdb/cb_bind.c | 196
ldap/servers/plugins/chainingdb/cb_compare.c | 101
ldap/servers/plugins/chainingdb/cb_config.c | 34
ldap/servers/plugins/chainingdb/cb_conn_stateless.c | 102
ldap/servers/plugins/chainingdb/cb_controls.c | 36
ldap/servers/plugins/chainingdb/cb_delete.c | 125
ldap/servers/plugins/chainingdb/cb_init.c | 6
ldap/servers/plugins/chainingdb/cb_instance.c | 325
ldap/servers/plugins/chainingdb/cb_modify.c | 133
ldap/servers/plugins/chainingdb/cb_modrdn.c | 176
ldap/servers/plugins/chainingdb/cb_monitor.c | 6
ldap/servers/plugins/chainingdb/cb_schema.c | 4
ldap/servers/plugins/chainingdb/cb_search.c | 223
ldap/servers/plugins/chainingdb/cb_utils.c | 15
ldap/servers/plugins/collation/collate.c | 24
ldap/servers/plugins/collation/orfilter.c | 19
ldap/servers/plugins/cos/cos.c | 52
ldap/servers/plugins/cos/cos_cache.c | 768
ldap/servers/plugins/deref/deref.c | 8
ldap/servers/plugins/dna/dna.c | 1783
ldap/servers/plugins/http/http_impl.c | 81
ldap/servers/plugins/linkedattrs/fixup_task.c | 119
ldap/servers/plugins/linkedattrs/linked_attrs.c | 237
ldap/servers/plugins/linkedattrs/linked_attrs.h | 9
ldap/servers/plugins/memberof/memberof.c | 841
ldap/servers/plugins/memberof/memberof.h | 11
ldap/servers/plugins/memberof/memberof_config.c | 275
ldap/servers/plugins/mep/mep.c | 2837
ldap/servers/plugins/mep/mep.h | 130
ldap/servers/plugins/pam_passthru/pam_passthru.h | 48
ldap/servers/plugins/pam_passthru/pam_ptconfig.c | 715
ldap/servers/plugins/pam_passthru/pam_ptimpl.c | 79
ldap/servers/plugins/pam_passthru/pam_ptpreop.c | 587
ldap/servers/plugins/passthru/passthru.h | 4
ldap/servers/plugins/passthru/ptbind.c | 6
ldap/servers/plugins/passthru/ptconfig.c | 43
ldap/servers/plugins/passthru/ptconn.c | 8
ldap/servers/plugins/passthru/ptpreop.c | 17
ldap/servers/plugins/pwdstorage/smd5_pwd.c | 9
ldap/servers/plugins/referint/referint.c | 775
ldap/servers/plugins/replication/cl4_api.c | 2
ldap/servers/plugins/replication/cl5.h | 1
ldap/servers/plugins/replication/cl5_api.c | 2679
ldap/servers/plugins/replication/cl5_api.h | 115
ldap/servers/plugins/replication/cl5_clcache.c | 55
ldap/servers/plugins/replication/cl5_clcache.h | 2
ldap/servers/plugins/replication/cl5_config.c | 247
ldap/servers/plugins/replication/cl5_init.c | 2
ldap/servers/plugins/replication/cl5_test.c | 2
ldap/servers/plugins/replication/cl_crypt.c | 203
ldap/servers/plugins/replication/cl_crypt.h | 53
ldap/servers/plugins/replication/csnpl.c | 74
ldap/servers/plugins/replication/legacy_consumer.c | 31
ldap/servers/plugins/replication/llist.c | 8
ldap/servers/plugins/replication/repl-session-plugin.h | 119
ldap/servers/plugins/replication/repl.h | 2
ldap/servers/plugins/replication/repl5.h | 88
ldap/servers/plugins/replication/repl5_agmt.c | 436
ldap/servers/plugins/replication/repl5_agmtlist.c | 119
ldap/servers/plugins/replication/repl5_connection.c | 155
ldap/servers/plugins/replication/repl5_inc_protocol.c | 1294
ldap/servers/plugins/replication/repl5_init.c | 112
ldap/servers/plugins/replication/repl5_mtnode_ext.c | 13
ldap/servers/plugins/replication/repl5_plugins.c | 208
ldap/servers/plugins/replication/repl5_prot_private.h | 4
ldap/servers/plugins/replication/repl5_protocol.c | 107
ldap/servers/plugins/replication/repl5_protocol_util.c | 563
ldap/servers/plugins/replication/repl5_replica.c | 404
ldap/servers/plugins/replication/repl5_replica_config.c | 726
ldap/servers/plugins/replication/repl5_replica_dnhash.c | 26
ldap/servers/plugins/replication/repl5_replica_hash.c | 30
ldap/servers/plugins/replication/repl5_ruv.c | 454
ldap/servers/plugins/replication/repl5_ruv.h | 18
ldap/servers/plugins/replication/repl5_tot_protocol.c | 32
ldap/servers/plugins/replication/repl5_total.c | 22
ldap/servers/plugins/replication/repl5_updatedn_list.c | 2
ldap/servers/plugins/replication/repl_bind.c | 6
ldap/servers/plugins/replication/repl_compare.c | 18
ldap/servers/plugins/replication/repl_connext.c | 2
ldap/servers/plugins/replication/repl_controls.c | 2
ldap/servers/plugins/replication/repl_extop.c | 640
ldap/servers/plugins/replication/repl_globals.c | 4
ldap/servers/plugins/replication/repl_init.c | 1
ldap/servers/plugins/replication/repl_objset.c | 9
ldap/servers/plugins/replication/repl_session_plugin.c | 188
ldap/servers/plugins/replication/repl_shared.h | 17
ldap/servers/plugins/replication/replutil.c | 110
ldap/servers/plugins/replication/test_repl_session_plugin.c | 335
ldap/servers/plugins/replication/urp.c | 182
ldap/servers/plugins/replication/urp.h | 3
ldap/servers/plugins/replication/urp_glue.c | 9
ldap/servers/plugins/replication/urp_tombstone.c | 9
ldap/servers/plugins/replication/windows_connection.c | 165
ldap/servers/plugins/replication/windows_inc_protocol.c | 55
ldap/servers/plugins/replication/windows_private.c | 456
ldap/servers/plugins/replication/windows_protocol_util.c | 861
ldap/servers/plugins/replication/windows_tot_protocol.c | 125
ldap/servers/plugins/replication/windowsrepl.h | 49
ldap/servers/plugins/replication/winsync-plugin.h | 336
ldap/servers/plugins/retrocl/retrocl.c | 51
ldap/servers/plugins/retrocl/retrocl.h | 2
ldap/servers/plugins/retrocl/retrocl_create.c | 13
ldap/servers/plugins/retrocl/retrocl_po.c | 20
ldap/servers/plugins/retrocl/retrocl_trim.c | 20
ldap/servers/plugins/rever/des.c | 72
ldap/servers/plugins/rever/rever.c | 8
ldap/servers/plugins/roles/roles_cache.c | 128
ldap/servers/plugins/roles/roles_plugin.c | 52
ldap/servers/plugins/schema_reload/schema_reload.c | 56
ldap/servers/plugins/shared/plugin-utils.h | 112
ldap/servers/plugins/shared/utils.c | 508
ldap/servers/plugins/statechange/statechange.c | 55
ldap/servers/plugins/syntaxes/bin.c | 142
ldap/servers/plugins/syntaxes/bitstring.c | 68
ldap/servers/plugins/syntaxes/ces.c | 172
ldap/servers/plugins/syntaxes/cis.c | 321
ldap/servers/plugins/syntaxes/deliverymethod.c | 32
ldap/servers/plugins/syntaxes/dn.c | 72
ldap/servers/plugins/syntaxes/facsimile.c | 32
ldap/servers/plugins/syntaxes/guide.c | 32
ldap/servers/plugins/syntaxes/int.c | 96
ldap/servers/plugins/syntaxes/nameoptuid.c | 72
ldap/servers/plugins/syntaxes/numericstring.c | 148
ldap/servers/plugins/syntaxes/sicis.c | 32
ldap/servers/plugins/syntaxes/string.c | 402
ldap/servers/plugins/syntaxes/syntax.h | 61
ldap/servers/plugins/syntaxes/syntax_common.c | 118
ldap/servers/plugins/syntaxes/tel.c | 94
ldap/servers/plugins/syntaxes/teletex.c | 32
ldap/servers/plugins/syntaxes/telex.c | 31
ldap/servers/plugins/syntaxes/validate.c | 17
ldap/servers/plugins/syntaxes/value.c | 120
ldap/servers/plugins/uiduniq/7bit.c | 76
ldap/servers/plugins/uiduniq/plugin-utils.h | 96
ldap/servers/plugins/uiduniq/uid.c | 342
ldap/servers/plugins/uiduniq/utils.c | 249
ldap/servers/plugins/usn/usn.c | 344
ldap/servers/plugins/usn/usn.h | 3
ldap/servers/plugins/usn/usn_cleanup.c | 44
ldap/servers/plugins/views/views.c | 36
ldap/servers/slapd/abandon.c | 8
ldap/servers/slapd/add.c | 257
ldap/servers/slapd/agtmmap.c | 56
ldap/servers/slapd/attr.c | 87
ldap/servers/slapd/attrlist.c | 7
ldap/servers/slapd/attrsyntax.c | 143
ldap/servers/slapd/auditlog.c | 70
ldap/servers/slapd/auth.c | 95
ldap/servers/slapd/ava.c | 2
ldap/servers/slapd/back-ldbm/ancestorid.c | 104
ldap/servers/slapd/back-ldbm/archive.c | 91
ldap/servers/slapd/back-ldbm/back-ldbm.h | 108
ldap/servers/slapd/back-ldbm/backentry.c | 6
ldap/servers/slapd/back-ldbm/cache.c | 134
ldap/servers/slapd/back-ldbm/dbhelp.c | 18
ldap/servers/slapd/back-ldbm/dblayer.c | 2279
ldap/servers/slapd/back-ldbm/dblayer.h | 14
ldap/servers/slapd/back-ldbm/dbtest.c | 349
ldap/servers/slapd/back-ldbm/dbversion.c | 52
ldap/servers/slapd/back-ldbm/dn2entry.c | 63
ldap/servers/slapd/back-ldbm/filterindex.c | 259
ldap/servers/slapd/back-ldbm/findentry.c | 147
ldap/servers/slapd/back-ldbm/id2entry.c | 189
ldap/servers/slapd/back-ldbm/idl.c | 35
ldap/servers/slapd/back-ldbm/idl_common.c | 7
ldap/servers/slapd/back-ldbm/idl_new.c | 111
ldap/servers/slapd/back-ldbm/idl_shim.c | 17
ldap/servers/slapd/back-ldbm/import-merge.c | 28
ldap/servers/slapd/back-ldbm/import-threads.c | 1385
ldap/servers/slapd/back-ldbm/import.c | 403
ldap/servers/slapd/back-ldbm/import.h | 32
ldap/servers/slapd/back-ldbm/index.c | 342
ldap/servers/slapd/back-ldbm/init.c | 89
ldap/servers/slapd/back-ldbm/instance.c | 174
ldap/servers/slapd/back-ldbm/ldbm_add.c | 415
ldap/servers/slapd/back-ldbm/ldbm_attr.c | 392
ldap/servers/slapd/back-ldbm/ldbm_attrcrypt.c | 986
ldap/servers/slapd/back-ldbm/ldbm_attrcrypt_config.c | 2
ldap/servers/slapd/back-ldbm/ldbm_bind.c | 9
ldap/servers/slapd/back-ldbm/ldbm_compare.c | 9
ldap/servers/slapd/back-ldbm/ldbm_config.c | 321
ldap/servers/slapd/back-ldbm/ldbm_config.h | 9
ldap/servers/slapd/back-ldbm/ldbm_delete.c | 598
ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c | 1583
ldap/servers/slapd/back-ldbm/ldbm_index_config.c | 668
ldap/servers/slapd/back-ldbm/ldbm_instance_config.c | 270
ldap/servers/slapd/back-ldbm/ldbm_modify.c | 334
ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 708
ldap/servers/slapd/back-ldbm/ldbm_search.c | 433
ldap/servers/slapd/back-ldbm/ldbm_usn.c | 74
ldap/servers/slapd/back-ldbm/ldif2ldbm.c | 792
ldap/servers/slapd/back-ldbm/matchrule.c | 50
ldap/servers/slapd/back-ldbm/misc.c | 300
ldap/servers/slapd/back-ldbm/monitor.c | 14
ldap/servers/slapd/back-ldbm/nextid.c | 17
ldap/servers/slapd/back-ldbm/parents.c | 141
ldap/servers/slapd/back-ldbm/perfctrs.c | 26
ldap/servers/slapd/back-ldbm/proto-back-ldbm.h | 55
ldap/servers/slapd/back-ldbm/seq.c | 3
ldap/servers/slapd/back-ldbm/sort.c | 38
ldap/servers/slapd/back-ldbm/start.c | 64
ldap/servers/slapd/back-ldbm/upgrade.c | 56
ldap/servers/slapd/back-ldbm/vlv.c | 388
ldap/servers/slapd/back-ldbm/vlv_srch.c | 17
ldap/servers/slapd/back-ldbm/vlv_srch.h | 3
ldap/servers/slapd/back-ldif/back-ldif.h | 2
ldap/servers/slapd/back-ldif/modrdn.c | 12
ldap/servers/slapd/backend.c | 72
ldap/servers/slapd/backend_manager.c | 18
ldap/servers/slapd/bind.c | 333
ldap/servers/slapd/bulk_import.c | 39
ldap/servers/slapd/charray.c | 32
ldap/servers/slapd/compare.c | 43
ldap/servers/slapd/computed.c | 36
ldap/servers/slapd/config.c | 19
ldap/servers/slapd/configdse.c | 68
ldap/servers/slapd/connection.c | 204
ldap/servers/slapd/conntable.c | 3
ldap/servers/slapd/control.c | 26
ldap/servers/slapd/csn.c | 77
ldap/servers/slapd/csngen.c | 54
ldap/servers/slapd/csnset.c | 4
ldap/servers/slapd/daemon.c | 694
ldap/servers/slapd/delete.c | 128
ldap/servers/slapd/dn.c | 1561
ldap/servers/slapd/dse.c | 788
ldap/servers/slapd/dynalib.c | 29
ldap/servers/slapd/entry.c | 940
ldap/servers/slapd/entrywsi.c | 128
ldap/servers/slapd/eventq.c | 4
ldap/servers/slapd/extendop.c | 35
ldap/servers/slapd/factory.c | 1
ldap/servers/slapd/fe.h | 5
ldap/servers/slapd/fedse.c | 40
ldap/servers/slapd/filter.c | 141
ldap/servers/slapd/filter.h | 1
ldap/servers/slapd/filtercmp.c | 26
ldap/servers/slapd/filterentry.c | 36
ldap/servers/slapd/generation.c | 1
ldap/servers/slapd/index_subsystem.c | 28
ldap/servers/slapd/intrinsics.h | 7
ldap/servers/slapd/ldaputil.c | 812
ldap/servers/slapd/lenstr.c | 6
ldap/servers/slapd/libglobs.c | 964
ldap/servers/slapd/libslapd.def | 1
ldap/servers/slapd/log.c | 144
ldap/servers/slapd/log.h | 20
ldap/servers/slapd/main.c | 291
ldap/servers/slapd/mapping_tree.c | 478
ldap/servers/slapd/match.c | 96
ldap/servers/slapd/modify.c | 540
ldap/servers/slapd/modrdn.c | 379
ldap/servers/slapd/modutil.c | 77
ldap/servers/slapd/operation.c | 38
ldap/servers/slapd/opshared.c | 396
ldap/servers/slapd/pagedresults.c | 581
ldap/servers/slapd/passwd_extop.c | 203
ldap/servers/slapd/pblock.c | 619
ldap/servers/slapd/plugin.c | 339
ldap/servers/slapd/plugin_acl.c | 24
ldap/servers/slapd/plugin_internal_op.c | 179
ldap/servers/slapd/plugin_mr.c | 474
ldap/servers/slapd/plugin_syntax.c | 442
ldap/servers/slapd/protect_db.c | 24
ldap/servers/slapd/protect_db.h | 7
ldap/servers/slapd/proto-slap.h | 122
ldap/servers/slapd/proxyauth.c | 246
ldap/servers/slapd/psearch.c | 76
ldap/servers/slapd/pw.c | 561
ldap/servers/slapd/pw.h | 7
ldap/servers/slapd/pw_mgmt.c | 159
ldap/servers/slapd/pw_retry.c | 109
ldap/servers/slapd/rdn.c | 141
ldap/servers/slapd/referral.c | 29
ldap/servers/slapd/regex.c | 31
ldap/servers/slapd/resourcelimit.c | 84
ldap/servers/slapd/result.c | 103
ldap/servers/slapd/rootdse.c | 12
ldap/servers/slapd/rwlock.c | 257
ldap/servers/slapd/rwlock.h | 65
ldap/servers/slapd/sasl_io.c | 167
ldap/servers/slapd/sasl_map.c | 63
ldap/servers/slapd/saslbind.c | 172
ldap/servers/slapd/schema.c | 204
ldap/servers/slapd/schemaparse.c | 13
ldap/servers/slapd/search.c | 92
ldap/servers/slapd/security_wrappers.c | 36
ldap/servers/slapd/slap.h | 247
ldap/servers/slapd/slapi-plugin-compat4.h | 6
ldap/servers/slapd/slapi-plugin.h | 1285
ldap/servers/slapd/slapi-private.h | 59
ldap/servers/slapd/slapi2nspr.c | 79
ldap/servers/slapd/slapi_counter.c | 24
ldap/servers/slapd/snmp_collator.c | 19
ldap/servers/slapd/sort.c | 9
ldap/servers/slapd/ssl.c | 323
ldap/servers/slapd/str2filter.c | 5
ldap/servers/slapd/task.c | 128
ldap/servers/slapd/test-plugins/testbind.c | 1
ldap/servers/slapd/test-plugins/testpostop.c | 1
ldap/servers/slapd/thread_data.c | 174
ldap/servers/slapd/time.c | 91
ldap/servers/slapd/tools/dbscan.c | 76
ldap/servers/slapd/tools/ldclt/data.c | 70
ldap/servers/slapd/tools/ldclt/ldapfct.c | 1149
ldap/servers/slapd/tools/ldclt/ldclt.c | 50
ldap/servers/slapd/tools/ldclt/ldclt.h | 3
ldap/servers/slapd/tools/ldclt/ldcltU.c | 24
ldap/servers/slapd/tools/ldclt/parser.c | 19
ldap/servers/slapd/tools/ldclt/scalab01.c | 190
ldap/servers/slapd/tools/ldclt/threadMain.c | 6
ldap/servers/slapd/tools/ldif.c | 4
ldap/servers/slapd/tools/mmldif.c | 9
ldap/servers/slapd/tools/pwenc.c | 2
ldap/servers/slapd/tools/rsearch/addthread.c | 51
ldap/servers/slapd/tools/rsearch/sdattable.c | 4
ldap/servers/slapd/tools/rsearch/searchthread.c | 94
ldap/servers/slapd/uniqueid.c | 99
ldap/servers/slapd/utf8compare.c | 6
ldap/servers/slapd/util.c | 357
ldap/servers/slapd/uuid.c | 22
ldap/servers/slapd/value.c | 53
ldap/servers/slapd/valueset.c | 75
ldap/servers/slapd/vattr.c | 115
ldap/servers/snmp/NETWORK-SERVICES-MIB.txt | 650
ldap/servers/snmp/RFC-1215.txt | 38
ldap/servers/snmp/RFC1155-SMI.txt | 119
ldap/servers/snmp/SNMPv2-CONF.txt | 322
ldap/servers/snmp/SNMPv2-SMI.txt | 344
ldap/servers/snmp/SNMPv2-TC.txt | 772
ldap/servers/snmp/ldap-agent.c | 26
ldap/servers/snmp/main.c | 12
ldap/servers/snmp/netscape-ldap.mib | 759
ldap/systools/idsktune.c | 100
lib/base/crit.cpp | 6
lib/base/ereport.cpp | 2
lib/base/file.cpp | 24
lib/base/lexer.cpp | 1015
lib/base/plist.cpp | 3
lib/base/pool.cpp | 10
lib/base/rwlock.cpp | 168
lib/base/util.cpp | 13
lib/ldaputil/cert.c | 4
lib/ldaputil/certmap.c | 409
lib/ldaputil/dbconf.c | 1
lib/ldaputil/utest/Makefile | 149
lib/ldaputil/utest/auth.cpp | 611
lib/ldaputil/utest/authtest | 138
lib/ldaputil/utest/certmap.conf | 68
lib/ldaputil/utest/dblist.conf | 47
lib/ldaputil/utest/example.c | 153
lib/ldaputil/utest/plugin.c | 152
lib/ldaputil/utest/plugin.h | 57
lib/ldaputil/utest/stubs.c | 144
lib/ldaputil/utest/stubs.cpp | 139
lib/ldaputil/utest/test.ref | 480
lib/ldaputil/vtable.c | 2
lib/libaccess/acl.tab.cpp | 25
lib/libaccess/aclcache.cpp | 105
lib/libaccess/aclflush.cpp | 1
lib/libaccess/aclpriv.h | 1
lib/libaccess/acltext.y | 4
lib/libaccess/acltools.cpp | 1896
lib/libaccess/aclutil.cpp | 13
lib/libaccess/authdb.cpp | 112
lib/libaccess/lasdns.cpp | 23
lib/libaccess/lasgroup.cpp | 10
lib/libaccess/lasip.cpp | 20
lib/libaccess/nseframe.cpp | 1
lib/libaccess/oneeval.cpp | 19
lib/libaccess/permhash.h | 11
lib/libaccess/register.cpp | 50
lib/libaccess/usrcache.cpp | 14
lib/libaccess/utest/.purify | 19
lib/libaccess/utest/Makefile | 147
lib/libaccess/utest/acl.dat | 44
lib/libaccess/utest/aclfile0 | 87
lib/libaccess/utest/aclfile1 | 43
lib/libaccess/utest/aclfile10 | 45
lib/libaccess/utest/aclfile11 | 43
lib/libaccess/utest/aclfile12 | 43
lib/libaccess/utest/aclfile13 | 43
lib/libaccess/utest/aclfile14 | 43
lib/libaccess/utest/aclfile15 | 43
lib/libaccess/utest/aclfile16 | 43
lib/libaccess/utest/aclfile17 | 43
lib/libaccess/utest/aclfile18 | 51
lib/libaccess/utest/aclfile19 | 46
lib/libaccess/utest/aclfile2 | 43
lib/libaccess/utest/aclfile3 | 43
lib/libaccess/utest/aclfile4 | 43
lib/libaccess/utest/aclfile5 | 43
lib/libaccess/utest/aclfile6 | 55
lib/libaccess/utest/aclfile7 | 43
lib/libaccess/utest/aclfile8 | 43
lib/libaccess/utest/aclfile9 | 43
lib/libaccess/utest/aclgrp0 | 42
lib/libaccess/utest/aclgrp1 | 42
lib/libaccess/utest/aclgrp2 | 42
lib/libaccess/utest/aclgrp3 | 42
lib/libaccess/utest/aclgrp4 | 42
lib/libaccess/utest/acltest.cpp | 794
lib/libaccess/utest/onetest.cpp | 77
lib/libaccess/utest/shexp.cpp | 331
lib/libaccess/utest/shexp.h | 168
lib/libaccess/utest/test.ref | 217
lib/libaccess/utest/testmain.cpp | 89
lib/libaccess/utest/twotest.cpp | 87
lib/libaccess/utest/ustubs.cpp | 331
lib/libadmin/error.c | 2
lib/libadmin/template.c | 2
lib/libadmin/util.c | 48
lib/libsi18n/coreres.c | 141
lib/libsi18n/coreres.h | 52
lib/libsi18n/getlang.c | 330
lib/libsi18n/getstrmem.c | 160
lib/libsi18n/getstrmem.h | 1
lib/libsi18n/getstrprop.c | 85
lib/libsi18n/makstrdb.c | 21
lib/libsi18n/propset.c | 442
lib/libsi18n/propset.h | 80
lib/libsi18n/reshash.c | 21
ltmain.sh |13199 ++-
m4/db.m4 | 27
m4/fhs.m4 | 4
m4/icu.m4 | 25
m4/kerberos.m4 | 4
m4/mozldap.m4 | 38
m4/netsnmp.m4 | 15
m4/nspr.m4 | 17
m4/nss.m4 | 17
m4/openldap.m4 | 30
m4/pcre.m4 | 28
m4/sasl.m4 | 25
m4/selinux.m4 | 13
m4/svrcore.m4 | 41
man/man1/cl-dump.1 | 18
man/man1/dbgen.pl.1 | 4
man/man1/infadd.1 | 8
man/man1/migratecred.1 | 6
man/man1/mmldif.1 | 4
man/man1/pwdhash.1 | 4
man/man1/repl-monitor.1 | 16
man/man8/ns-slapd.8 | 10
man/man8/remove-ds.pl.8 | 6
man/man8/restart-dirsrv.8 | 50
man/man8/setup-ds.pl.8 | 4
man/man8/start-dirsrv.8 | 50
man/man8/stop-dirsrv.8 | 50
missing | 104
selinux/dirsrv.fc.in | 2
selinux/dirsrv.if | 41
selinux/dirsrv.te | 11
wrappers/cl-dump.in | 11
wrappers/dbscan.in | 10
wrappers/infadd.in | 12
wrappers/initscript.in | 244
wrappers/ldap-agent-initscript.in | 20
wrappers/ldap-agent.in | 12
wrappers/ldclt.in | 12
wrappers/ldif.in | 12
wrappers/migratecred.in | 14
wrappers/mmldif.in | 14
wrappers/pwdhash.in | 14
wrappers/repl-monitor.in | 11
wrappers/rsearch.in | 12
wrappers/systemd-snmp.service.in | 16
wrappers/systemd.group.in | 6
wrappers/systemd.template.service.in | 28
wrappers/systemd.template.sysconfig | 3
628 files changed, 90050 insertions(+), 70641 deletions(-)
---
11 years, 6 months
Branch '389-ds-base-1.2.11' - VERSION.sh
by Richard Allen Megginson
VERSION.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
New commits:
commit aa952c12443d8fbc1aca331fb42e653290167a82
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Thu May 24 14:43:12 2012 -0600
bump version to 1.2.11.4
diff --git a/VERSION.sh b/VERSION.sh
index 673f16b..a3ed29a 100644
--- a/VERSION.sh
+++ b/VERSION.sh
@@ -10,7 +10,7 @@ vendor="389 Project"
# PACKAGE_VERSION is constructed from these
VERSION_MAJOR=1
VERSION_MINOR=2
-VERSION_MAINT=11.3
+VERSION_MAINT=11.4
# if this is a PRERELEASE, set VERSION_PREREL
# otherwise, comment it out
# be sure to include the dot prefix in the prerel
11 years, 6 months
3 commits - ldap/servers
by Richard Allen Megginson
ldap/servers/plugins/replication/repl5_plugins.c | 5
ldap/servers/plugins/usn/usn.c | 47 --
ldap/servers/plugins/usn/usn_cleanup.c | 3
ldap/servers/slapd/add.c | 7
ldap/servers/slapd/back-ldbm/cache.c | 53 +-
ldap/servers/slapd/back-ldbm/dblayer.c | 420 ++++++++++++++++++++
ldap/servers/slapd/back-ldbm/index.c | 62 ++
ldap/servers/slapd/back-ldbm/ldbm_add.c | 2
ldap/servers/slapd/back-ldbm/ldbm_delete.c | 152 ++++---
ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c | 476 +++++++++++++++++------
ldap/servers/slapd/back-ldbm/ldbm_modify.c | 15
ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 245 ++++++-----
ldap/servers/slapd/back-ldbm/misc.c | 2
ldap/servers/slapd/back-ldbm/seq.c | 3
ldap/servers/slapd/slap.h | 3
15 files changed, 1122 insertions(+), 373 deletions(-)
New commits:
commit c3dc979e962796dbbfba7dbc3ae49caacf2f2ee4
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Wed May 23 19:23:24 2012 -0600
Ticket #383 - usn + mmr = deletions are not replicated
https://fedorahosted.org/389/ticket/383
Resolves: Ticket #383
Bug Description: usn + mmr = deletions are not replicated
Reviewed by: mreynolds (Thanks!)
Branch: master
Fix Description: The problem was that because usn was creating a tombstone,
it was also setting the OP_FLAG_TOMBSTONE flag in the operation, which was
causing the operation to think it was deleting a tombstone. The fix is to
not set this flag, and instead have operations that delete tombstones to
set that flag explicitly when creating the delete op request.
In addition, the CSN for delete ops was not being logged - the usn bepostop
was deleting it, even when replication was being used. Previously the csn
was needed as a "trigger" to tell the ldbm_back_delete code to create a
tombstone rather than deleting the entry outright. Instead, use the
slapi_operation_get_replica_attr (pb, operation,
"nsds5ReplicaTombstonePurgeInterval,
&create_tombstone_entry)
to determine whether or not to create a tombstone entry. Both replication
and usn configure this, so if using one or both of those, tombstones will
be created, otherwise, not.
Platforms tested: RHEL6 x86_64, Fedora 17
Flag Day: no
Doc impact: no
(cherry picked from commit 73e077189820130c93e25e359d5935794dbbf3ee)
diff --git a/ldap/servers/plugins/usn/usn.c b/ldap/servers/plugins/usn/usn.c
index 812d83d..0273fd1 100644
--- a/ldap/servers/plugins/usn/usn.c
+++ b/ldap/servers/plugins/usn/usn.c
@@ -45,8 +45,6 @@ static Slapi_PluginDesc pdesc = {
"USN", VENDOR, DS_PACKAGE_VERSION,
"USN (Update Sequence Number) plugin" };
-static CSNGen *_usn_csngen = NULL;
-
static void *_usn_identity = NULL;
static int usn_preop_init(Slapi_PBlock *pb);
@@ -152,13 +150,6 @@ usn_preop_init(Slapi_PBlock *pb)
{
int rc = 0;
int predel = SLAPI_PLUGIN_PRE_DELETE_FN;
- /* set up csn generator for tombstone */
- _usn_csngen = csngen_new(USN_CSNGEN_ID, NULL);
- if (NULL == _usn_csngen) {
- slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
- "usn_preop_init: csngen_new failed\n");
- rc = -1;
- }
if (slapi_pblock_set(pb, predel, (void *)usn_preop_delete) != 0) {
slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
@@ -302,15 +293,11 @@ bail:
return rc;
}
-/*
- * usn_close: release the csn generator used to convert an entry to tombstone
- */
static int
usn_close(Slapi_PBlock *pb)
{
slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM, "--> usn_close\n");
- csngen_free(&_usn_csngen);
g_plugin_started = 0;
slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM, "<-- usn_close\n");
@@ -325,32 +312,14 @@ static int
usn_preop_delete(Slapi_PBlock *pb)
{
int rc = 0;
- CSN *csn = NULL;
- CSN *orig_csn = NULL;
Slapi_Operation *op = NULL;
slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
"--> usn_preop_delete\n");
slapi_pblock_get(pb, SLAPI_OPERATION, &op);
- orig_csn = operation_get_csn(op);
-
- if (NULL == orig_csn) {
- /*
- * No other plugins hasn't set csn yet, so let's set USN's csn.
- * If other plugin overrides csn and replica_attr_handler, that's fine.
- */
- rc = csngen_new_csn(_usn_csngen, &csn, PR_FALSE /* notify */);
- if (CSN_SUCCESS != rc) {
- slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
- "usn_preop_delete: csngen_new failed (%d)\n", rc);
- csn_free(&csn);
- goto bail;
- }
- operation_set_csn(op, csn);
- slapi_operation_set_replica_attr_handler(op, (void *)usn_get_attr);
- }
-bail:
+ slapi_operation_set_replica_attr_handler(op, (void *)usn_get_attr);
+
slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
"<-- usn_preop_delete\n");
@@ -486,11 +455,6 @@ usn_betxnpreop_delete(Slapi_PBlock *pb)
rc = LDAP_PARAM_ERROR;
goto bail;
}
- if (e->e_flags & SLAPI_ENTRY_FLAG_TOMBSTONE) {
- Slapi_Operation *op = NULL;
- slapi_pblock_get(pb, SLAPI_OPERATION, &op);
- slapi_operation_set_flag(op, OP_FLAG_TOMBSTONE_ENTRY);
- }
_usn_add_next_usn(e, be);
bail:
slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
@@ -615,17 +579,10 @@ usn_bepostop_delete (Slapi_PBlock *pb)
{
int rc = -1;
Slapi_Backend *be = NULL;
- Slapi_Operation *op = NULL;
- CSN *csn = NULL;
slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
"--> usn_bepostop\n");
- slapi_pblock_get(pb, SLAPI_OPERATION, &op);
- csn = operation_get_csn(op);
- csn_free(&csn);
- operation_set_csn(op, NULL);
-
/* if op is not successful, don't increment the counter */
slapi_pblock_get(pb, SLAPI_RESULT_CODE, &rc);
if (LDAP_SUCCESS != rc) {
diff --git a/ldap/servers/plugins/usn/usn_cleanup.c b/ldap/servers/plugins/usn/usn_cleanup.c
index 20decae..6f9410e 100644
--- a/ldap/servers/plugins/usn/usn_cleanup.c
+++ b/ldap/servers/plugins/usn/usn_cleanup.c
@@ -145,6 +145,7 @@ usn_cleanup_thread(void *arg)
for (ep = entries; ep && *ep; ep++) {
int delrv = 0;
const Slapi_DN *sdn = slapi_entry_get_sdn_const(*ep);
+ int opflags = OP_FLAG_TOMBSTONE_ENTRY;
/* check for shutdown */
if(g_get_shutdown()){
@@ -156,7 +157,7 @@ usn_cleanup_thread(void *arg)
}
slapi_delete_internal_set_pb(delete_pb, slapi_sdn_get_dn(sdn),
- NULL, NULL, usn_get_identity(), 0);
+ NULL, NULL, usn_get_identity(), opflags);
slapi_delete_internal_pb(delete_pb);
slapi_pblock_get(delete_pb, SLAPI_PLUGIN_INTOP_RESULT, &delrv);
if (LDAP_SUCCESS != delrv) {
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
index 846d87b..0427b45 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
@@ -267,12 +267,8 @@ ldbm_back_delete( Slapi_PBlock *pb )
opcsn = operation_get_csn (operation);
if (!delete_tombstone_entry)
{
- /* If both USN and replication is enabled, csn set by replication
- * should be honored. */
- if ((opcsn == NULL || ldbm_usn_enabled(be)) &&
- !is_fixup_operation && operation->o_csngen_handler)
+ if ((opcsn == NULL) && !is_fixup_operation && operation->o_csngen_handler)
{
- csn_free(&opcsn); /* free opcsn set by USN plugin, if any */
/*
* Current op is a user request. Opcsn will be assigned
* by entry_assign_operation_csn() if the dn is in an
@@ -286,14 +282,15 @@ ldbm_back_delete( Slapi_PBlock *pb )
{
entry_set_maxcsn (e->ep_entry, opcsn);
}
- /*
- * We are dealing with replication and if we haven't been called to
- * remove a tombstone, then it's because we want to create a new one.
- */
- if ( slapi_operation_get_replica_attr (pb, operation, "nsds5ReplicaTombstonePurgeInterval", &create_tombstone_entry) == 0)
- {
- create_tombstone_entry = (create_tombstone_entry < 0) ? 0 : 1;
- }
+ }
+ /*
+ * We are dealing with replication and if we haven't been called to
+ * remove a tombstone, then it's because we want to create a new one.
+ */
+ if ( slapi_operation_get_replica_attr (pb, operation, "nsds5ReplicaTombstonePurgeInterval",
+ &create_tombstone_entry) == 0 )
+ {
+ create_tombstone_entry = (create_tombstone_entry < 0) ? 0 : 1;
}
}
commit 02f0106ec0b2225f7962a9fec0912a5414904b72
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Wed May 23 09:46:30 2012 -0600
Ticket #382 - DS Shuts down intermittently
https://fedorahosted.org/389/ticket/382
Resolves: Ticket #382
Bug Description: DS Shuts down intermittently
Reviewed by: nhosoi (Thanks!)
Branch: master
Fix Description: ldbm_back_delete should not touch the backentry to
be deleted while it is in the cache. Any mods made by any plugins should
be made to the tombstone or to a copy of the original entry.
Platforms tested: Fedora 17
Flag Day: no
Doc impact: no
(cherry picked from commit 7146bb325de67b036dfa39b898c030ee414337f9)
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
index 237085c..846d87b 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
@@ -60,7 +60,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
struct ldbminfo *li = NULL;
struct backentry *e = NULL;
struct backentry *tombstone = NULL;
- Slapi_Entry *original_entry = NULL;
struct backentry *original_tombstone = NULL;
char *dn = NULL;
back_txn txn;
@@ -80,7 +79,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
Slapi_DN sdn;
Slapi_DN *sdnp = NULL;
char *e_uniqueid = NULL;
- Slapi_DN *nscpEntrySDN = NULL;
+ Slapi_DN nscpEntrySDN;
int dblock_acquired= 0;
Slapi_Operation *operation;
CSN *opcsn = NULL;
@@ -110,6 +109,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
/* sdn needs to be initialized before "goto *_return */
slapi_sdn_init(&sdn);
+ slapi_sdn_init(&nscpEntrySDN);
/* dblayer_txn_init needs to be called before "goto error_return" */
dblayer_txn_init(li,&txn);
@@ -388,7 +388,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
childuniqueid);
Slapi_Value *tomb_value;
- nscpEntrySDN = slapi_entry_get_sdn(e->ep_entry);
+ slapi_sdn_set_ndn_byval(&nscpEntrySDN, slapi_sdn_get_ndn(slapi_entry_get_sdn(e->ep_entry)));
/* Copy the entry unique_id for URP conflict checking */
e_uniqueid = slapi_ch_strdup(childuniqueid);
@@ -418,10 +418,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
/* The suffix entry has no parent */
slapi_entry_add_string(tombstone->ep_entry, SLAPI_ATTR_VALUE_PARENT_UNIQUEID, parentuniqueid);
}
- if(nscpEntrySDN!=NULL)
- {
- slapi_entry_add_string(tombstone->ep_entry, SLAPI_ATTR_NSCP_ENTRYDN, slapi_sdn_get_ndn(nscpEntrySDN));
- }
+ slapi_entry_add_string(tombstone->ep_entry, SLAPI_ATTR_NSCP_ENTRYDN, slapi_sdn_get_ndn(&nscpEntrySDN));
tomb_value = slapi_value_new_string(SLAPI_ATTR_VALUE_TOMBSTONE);
value_update_csn(tomb_value, CSN_TYPE_VALUE_UPDATED,
operation_get_csn(operation));
@@ -449,11 +446,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
}
}
- if ( (original_entry = slapi_entry_dup( e->ep_entry )) == NULL ) {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
-
/*
* So, we believe that no code up till here actually added anything
* to the persistent store. From now on, we're transacted
@@ -469,20 +461,14 @@ ldbm_back_delete( Slapi_PBlock *pb )
/* reset original entry */
slapi_pblock_get( pb, SLAPI_DELETE_EXISTING_ENTRY, &ent );
- if (ent && (ent != original_entry) && free_delete_existing_entry) {
+ if (ent && free_delete_existing_entry) {
slapi_entry_free(ent);
slapi_pblock_set( pb, SLAPI_DELETE_EXISTING_ENTRY, NULL );
}
- slapi_entry_free(e->ep_entry);
- e->ep_entry = original_entry;
- if ( (original_entry = slapi_entry_dup( e->ep_entry )) == NULL ) {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
- slapi_pblock_set( pb, SLAPI_DELETE_EXISTING_ENTRY, original_entry );
- free_delete_existing_entry = 0; /* owned by original_entry now */
- if (nscpEntrySDN) {
- nscpEntrySDN = slapi_entry_get_sdn(original_entry);
+ slapi_pblock_set( pb, SLAPI_DELETE_EXISTING_ENTRY, slapi_entry_dup( e->ep_entry ) );
+ free_delete_existing_entry = 1; /* must free the dup */
+ if (create_tombstone_entry) {
+ slapi_sdn_set_ndn_byval(&nscpEntrySDN, slapi_sdn_get_ndn(slapi_entry_get_sdn(e->ep_entry)));
}
/* reset tombstone entry */
@@ -524,8 +510,10 @@ ldbm_back_delete( Slapi_PBlock *pb )
/* call the transaction pre delete plugins just after creating
* the transaction */
- slapi_pblock_get( pb, SLAPI_DELETE_BEPREOP_ENTRY, &orig_entry );
- slapi_pblock_set( pb, SLAPI_DELETE_BEPREOP_ENTRY, e->ep_entry );
+ /* these should not need to modify the entry to be deleted -
+ if for some reason they ever do, do not use e->ep_entry since
+ it could be in the cache and referenced by other search threads -
+ instead, have them modify a copy of the entry */
retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN);
if (retval) {
LDAPDebug1Arg( LDAP_DEBUG_TRACE,
@@ -544,13 +532,12 @@ ldbm_back_delete( Slapi_PBlock *pb )
}
goto error_return;
}
- slapi_pblock_set( pb, SLAPI_DELETE_BEPREOP_ENTRY, orig_entry );
- orig_entry = NULL;
if(create_tombstone_entry)
{
-
slapi_pblock_get( pb, SLAPI_DELETE_BEPREOP_ENTRY, &orig_entry );
+ /* this is ok because no other threads should be accessing
+ the tombstone entry */
slapi_pblock_set( pb, SLAPI_DELETE_BEPREOP_ENTRY,
tombstone->ep_entry );
rc = plugin_call_plugins(pb,
@@ -696,7 +683,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
goto error_return;
}
retval = index_addordel_string(be, SLAPI_ATTR_NSCP_ENTRYDN,
- slapi_sdn_get_ndn(nscpEntrySDN),
+ slapi_sdn_get_ndn(&nscpEntrySDN),
tombstone->ep_id, BE_INDEX_ADD, &txn);
if (DB_LOCK_DEADLOCK == retval) {
LDAPDebug( LDAP_DEBUG_ARGS,
@@ -1183,13 +1170,13 @@ diskfull_return:
}
if (free_delete_existing_entry) {
done_with_pblock_entry(pb, SLAPI_DELETE_EXISTING_ENTRY);
- } else { /* owned by original_entry */
+ } else { /* owned by someone else */
slapi_pblock_set(pb, SLAPI_DELETE_EXISTING_ENTRY, NULL);
}
- slapi_entry_free(original_entry);
backentry_free(&original_tombstone);
slapi_ch_free((void**)&errbuf);
slapi_sdn_done(&sdn);
+ slapi_sdn_done(&nscpEntrySDN);
slapi_ch_free_string(&e_uniqueid);
if (pb->pb_conn)
{
commit dadcd7890ff5e44b7b9e30ac36290559287b9ed2
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Mon May 14 15:14:28 2012 -0600
Ticket #360 - ldapmodify returns Operations error
https://fedorahosted.org/389/ticket/360
Resolves: Ticket #360
Bug Description: ldapmodify returns Operations error
Reviewed by: mreynolds (Thanks!)
Branch: master
Fix Description:
1) Fix handling of DB_LOCK_DEADLOCK conditions. When a database operation
returns DB_LOCK_DEADLOCK, all cursors must be closed, and the transaction
aborted and retried. If not in a transaction, the operation may be retried
immediately. This fix adds this logic to many places in the db code where
it was lacking.
2) Fix resetting of the data when an operation has to be retried. When
a transaction has to be retried, we must reset the data to the same state
it was before any of the operations in the transaction were attempted. This
includes the entry cache state, which was lacking in a number of ways. One
major problem with resetting the cache is that cache_add_tentative adds an
entry to the dncache, but not the idcache, in order to reserve a space in
the cache, and to prevent other entries with the same DN from being added
while the operation is in progress. There was no good way to remove this
entry. In the case of modrdn, removing the tentative entry would also
remove the real entry since they share the same entryid. This fix also
makes sure that in error conditions, temporary entries are removed from
the cache and properly freed, and real entries are "rolled back" into the
cache.
3) Added a transaction stress thread. This thread can simulate various types
of read and write locking that can cause conflicts and trigger regular
database operations to return DB_LOCK_DEADLOCK. The usual culprit is read
locks which are held on pages that are searched outside of a transaction.
The stress thread can lock, via read cursors, all of the pages in all of
the indexes in the database, and hold these pages for some set period of
time, then loop and do it again.
4) It is quite easy to get the database in a deadlock situation, where a
update operation is waiting for a read lock to be released in order to
write to a page, while a search operation is waiting for a write lock to
be released in order to read lock the page. If we are going to allow
concurrent searches during update operations, without making search requests
transacted, we need to have some way to detect these deadlocks. The fastest
way to do it is to use the DB_TXN_NOWAIT flag when starting transactions.
This tells bdb to return immediately with a DB_LOCK_DEADLOCK if the
transaction cannot proceed due to a locked page (e.g. a search request
has read locked a page). Alternately, we could have transactions wait
for some specified period of time, but if we think that this type of thread
contention is going to be rare, it makes sense to return immediately, if
our deadlock handling is fast and robust.
5) Fixed some memory leaks
6) The txn_test thread needs to know when the backend databases are
available - had to add a backend flag BE_STATE_STOPPING so that
the txn_thread knows when the databases are available
7) If the op was retried RETRY_TIMES times, return LDAP_BUSY instead of
OPERATIONS_ERROR - the problem really is that the server is busy with
other transactions, and the operation could go through if the client
were to retry.
8) Renaming an entry without changing the dn e.g. changing the case does
not cache the entry, so handle that
9) Added a delay when a deadlock is encountered in modrdn - same as the
other add/mod/del cases
Platforms tested: RHEL6 x86_64, Fedora 17
Flag Day: yes
Doc impact: yes
(cherry picked from commit 48b8ace54583662306c75f22f2f243fc274251af)
diff --git a/ldap/servers/plugins/replication/repl5_plugins.c b/ldap/servers/plugins/replication/repl5_plugins.c
index a768edb..2b4d0c9 100644
--- a/ldap/servers/plugins/replication/repl5_plugins.c
+++ b/ldap/servers/plugins/replication/repl5_plugins.c
@@ -1007,6 +1007,11 @@ write_changelog_and_ruv (Slapi_PBlock *pb)
return 0;
}
+ slapi_pblock_get(pb, SLAPI_RESULT_CODE, &rc);
+ if (rc) { /* op failed - just return */
+ return 0;
+ }
+
/* we only log changes for operations applied to a replica */
repl_obj = replica_get_replica_for_op (pb);
if (repl_obj == NULL)
diff --git a/ldap/servers/slapd/add.c b/ldap/servers/slapd/add.c
index 9966a27..55deeee 100644
--- a/ldap/servers/slapd/add.c
+++ b/ldap/servers/slapd/add.c
@@ -665,6 +665,7 @@ static void op_shared_add (Slapi_PBlock *pb)
int rc;
Slapi_Entry *ec;
Slapi_DN *add_target_sdn = NULL;
+ Slapi_Entry *save_e = NULL;
slapi_pblock_set(pb, SLAPI_PLUGIN, be->be_database);
set_db_default_result_handlers(pb);
@@ -678,6 +679,8 @@ static void op_shared_add (Slapi_PBlock *pb)
if (be->be_add != NULL)
{
rc = (*be->be_add)(pb);
+ /* backend may change this if errors and not consumed */
+ slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &save_e);
slapi_pblock_set(pb, SLAPI_ADD_ENTRY, ec);
if (rc == 0)
{
@@ -703,6 +706,10 @@ static void op_shared_add (Slapi_PBlock *pb)
}
else
{
+ /* restore e so we can free it below */
+ if (save_e) {
+ e = save_e;
+ }
if (rc == SLAPI_FAIL_DISKFULL)
{
operation_out_of_disk_space();
diff --git a/ldap/servers/slapd/back-ldbm/cache.c b/ldap/servers/slapd/back-ldbm/cache.c
index 2ef0f28..045b1eb 100644
--- a/ldap/servers/slapd/back-ldbm/cache.c
+++ b/ldap/servers/slapd/back-ldbm/cache.c
@@ -294,7 +294,7 @@ dump_hash(Hashtable *ht)
continue;
}
do {
- PR_snprintf(ep_id, 16, "%u", ((struct backcommon *)e)->ep_id);
+ PR_snprintf(ep_id, 16, "%u-%u", ((struct backcommon *)e)->ep_id, ((struct backcommon *)e)->ep_refcnt);
len = strlen(ep_id);
if (ids_size < len + 1) {
LDAPDebug1Arg(LDAP_DEBUG_ANY, "%s\n", ep_ids);
@@ -857,7 +857,7 @@ entrycache_remove_int(struct cache *cache, struct backentry *e)
const char *uuid;
#endif
- LOG("=> entrycache_remove_int (%s)\n", backentry_get_ndn(e), 0, 0);
+ LOG("=> entrycache_remove_int (%s) (%u) (%u)\n", backentry_get_ndn(e), e->ep_id, e->ep_refcnt);
if (e->ep_state & ENTRY_STATE_NOTINCACHE)
{
return ret;
@@ -876,13 +876,22 @@ entrycache_remove_int(struct cache *cache, struct backentry *e)
{
LOG("remove %s from dn hash failed\n", ndn, 0, 0);
}
- if (remove_hash(cache->c_idtable, &(e->ep_id), sizeof(ID)))
+ /* if entry was added tentatively, it will be in the dntable
+ but not in the idtable - we cannot just remove it from
+ the idtable - in the case of modrdn, this will remove
+ the _real_ entry from the idtable, leading to a cache
+ imbalance
+ */
+ if (!(e->ep_state & ENTRY_STATE_CREATING))
{
- ret = 0;
- }
- else
- {
- LOG("remove %d from id hash failed\n", e->ep_id, 0, 0);
+ if (remove_hash(cache->c_idtable, &(e->ep_id), sizeof(ID)))
+ {
+ ret = 0;
+ }
+ else
+ {
+ LOG("remove %d from id hash failed\n", e->ep_id, 0, 0);
+ }
}
#ifdef UUIDCACHE_ON
uuid = slapi_entry_get_uniqueid(e->ep_entry);
@@ -907,6 +916,11 @@ entrycache_remove_int(struct cache *cache, struct backentry *e)
/* mark for deletion (will be erased when refcount drops to zero) */
e->ep_state |= ENTRY_STATE_DELETED;
+#if 0
+ if (slapi_is_loglevel_set(SLAPI_LOG_CACHE)) {
+ dump_hash(cache->c_idtable);
+ }
+#endif
LOG("<= entrycache_remove_int: %d\n", ret, 0, 0);
return ret;
}
@@ -999,14 +1013,23 @@ static int entrycache_replace(struct cache *cache, struct backentry *olde,
* cache tables, operation error
*/
if ( (olde->ep_state & ENTRY_STATE_NOTINCACHE) == 0 ) {
-
- found = remove_hash(cache->c_dntable, (void *)oldndn, strlen(oldndn));
- found &= remove_hash(cache->c_idtable, &(olde->ep_id), sizeof(ID));
+ int found_in_dn = remove_hash(cache->c_dntable, (void *)oldndn, strlen(oldndn));
+ int found_in_id = remove_hash(cache->c_idtable, &(olde->ep_id), sizeof(ID));
+#ifdef UUIDCACHE_ON
+ int found_in_uuid = remove_hash(cache->c_uuidtable, (void *)olduuid, strlen(olduuid));
+#endif
+ found = found_in_dn && found_in_id;
#ifdef UUIDCACHE_ON
- found &= remove_hash(cache->c_uuidtable, (void *)olduuid, strlen(olduuid));
+ found = found && found_in_uuid;
#endif
if (!found) {
- LOG("entry cache replace: cache index tables out of sync\n", 0, 0, 0);
+#ifdef UUIDCACHE_ON
+ LOG("entry cache replace: cache index tables out of sync - found dn [%d] id [%d] uuid [%d]\n",
+ found_in_dn, found_in_id, found_in_uuid);
+#else
+ LOG("entry cache replace: cache index tables out of sync - found dn [%d] id [%d]\n",
+ found_in_dn, found_in_id, 0);
+#endif
PR_Unlock(cache->c_mutex);
return 1;
}
@@ -1472,7 +1495,9 @@ int cache_lock_entry(struct cache *cache, struct backentry *e)
void cache_unlock_entry(struct cache *cache, struct backentry *e)
{
LOG("=> cache_unlock_entry\n", 0, 0, 0);
- PR_ExitMonitor(e->ep_mutexp);
+ if (PR_ExitMonitor(e->ep_mutexp)) {
+ LOG("=> cache_unlock_entry - monitor was not entered!!!\n", 0, 0, 0);
+ }
}
/* DN cache */
diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c
index 132b2b9..09d10a0 100644
--- a/ldap/servers/slapd/back-ldbm/dblayer.c
+++ b/ldap/servers/slapd/back-ldbm/dblayer.c
@@ -214,6 +214,7 @@ static int dblayer_start_deadlock_thread(struct ldbminfo *li);
static int dblayer_start_checkpoint_thread(struct ldbminfo *li);
static int dblayer_start_trickle_thread(struct ldbminfo *li);
static int dblayer_start_perf_thread(struct ldbminfo *li);
+static int dblayer_start_txn_test_thread(struct ldbminfo *li);
static int trans_batch_count=1;
static int trans_batch_limit=0;
static PRBool log_flush_thread=PR_FALSE;
@@ -226,6 +227,14 @@ static void dblayer_pop_pvt_txn();
#define MEGABYTE (1024 * 1024)
#define GIGABYTE (1024 * MEGABYTE)
+/* env. vars. you can set to stress txn handling */
+#define TXN_TESTING "TXN_TESTING" /* enables the txn test thread */
+#define TXN_TEST_HOLD_MSEC "TXN_TEST_HOLD_MSEC" /* time to hold open the db cursors */
+#define TXN_TEST_LOOP_MSEC "TXN_TEST_LOOP_MSEC" /* time to wait before looping again */
+#define TXN_TEST_USE_TXN "TXN_TEST_USE_TXN" /* use transactions or not */
+#define TXN_TEST_USE_RMW "TXN_TEST_USE_RMW" /* use DB_RMW for c_get flags or not */
+#define TXN_TEST_INDEXES "TXN_TEST_INDEXES" /* list of indexes to use - comma delimited - id2entry,entryrdn,etc. */
+#define TXN_TEST_VERBOSE "TXN_TEST_VERBOSE" /* be wordy */
/* This function compares two index keys. It is assumed
that the values are already normalized, since they should have
@@ -1755,6 +1764,9 @@ dblayer_start(struct ldbminfo *li, int dbmode)
/* Now open the performance counters stuff */
perfctrs_init(li,&(priv->perf_private));
+ if (getenv(TXN_TESTING)) {
+ dblayer_start_txn_test_thread(li);
+ }
}
if (return_value != 0) {
if (return_value == ENOMEM) {
@@ -2597,7 +2609,10 @@ int dblayer_instance_close(backend *be)
if (NULL == inst)
return -1;
- if (getenv("USE_VALGRIND")) {
+ if (!inst->import_env) {
+ be->be_state = BE_STATE_STOPPING;
+ }
+ if (getenv("USE_VALGRIND") || slapi_is_loglevel_set(SLAPI_LOG_CACHE)) {
/*
* if any string is set to an environment variable USE_VALGRIND,
* when running a memory leak checking tool (e.g., valgrind),
@@ -3422,7 +3437,7 @@ int dblayer_txn_begin_ext(struct ldbminfo *li, back_txnid parent_txn, back_txn *
return_value = TXN_BEGIN(pEnv->dblayer_DB_ENV,
(DB_TXN*)parent_txn,
&new_txn.back_txn_txn,
- 0);
+ DB_TXN_NOWAIT);
if (0 != return_value)
{
if(use_lock) slapi_rwlock_unlock(priv->dblayer_env->dblayer_env_lock);
@@ -3725,6 +3740,407 @@ dblayer_start_deadlock_thread(struct ldbminfo *li)
return return_value;
}
+static const u_int32_t default_flags = DB_NEXT;
+
+/* this is the loop delay - how long after we release the db pages
+ until we acquire them again */
+#define TXN_TEST_LOOP_WAIT(msecs) do { \
+ if (msecs) { \
+ DS_Sleep(PR_MillisecondsToInterval(slapi_rand() % msecs)); \
+ } \
+} while (0)
+
+/* this is how long we hold the pages open until we close the cursors */
+#define TXN_TEST_PAGE_HOLD(msecs) do { \
+ if (msecs) { \
+ DS_Sleep(PR_MillisecondsToInterval(slapi_rand() % msecs)); \
+ } \
+} while (0)
+
+typedef struct txn_test_iter {
+ DB *db;
+ DBC *cur;
+ size_t cnt;
+ const char *attr;
+ u_int32_t flags;
+ backend *be;
+} txn_test_iter;
+
+typedef struct txn_test_cfg {
+ PRUint32 hold_msec;
+ PRUint32 loop_msec;
+ u_int32_t flags;
+ int use_txn;
+ char **indexes;
+ int verbose;
+} txn_test_cfg;
+
+static txn_test_iter *
+new_txn_test_iter(DB *db, const char *attr, backend *be, u_int32_t flags)
+{
+ txn_test_iter *tti = (txn_test_iter *)slapi_ch_malloc(sizeof(txn_test_iter));
+ tti->db = db;
+ tti->cur = NULL;
+ tti->cnt = 0;
+ tti->attr = attr;
+ tti->flags = default_flags|flags;
+ tti->be = be;
+ return tti;
+}
+
+static void
+init_txn_test_iter(txn_test_iter *tti)
+{
+ if (tti->cur) {
+ if (tti->cur->dbp && (tti->cur->dbp->open_flags == 0x58585858)) {
+ /* already closed? */
+ } else if (tti->be && (tti->be->be_state != BE_STATE_STARTED)) {
+ /* already closed? */
+ } else {
+ tti->cur->c_close(tti->cur);
+ }
+ tti->cur = NULL;
+ }
+ tti->cnt = 0;
+ tti->flags = default_flags;
+}
+
+static void
+free_txn_test_iter(txn_test_iter *tti)
+{
+ init_txn_test_iter(tti);
+ slapi_ch_free((void **)&tti);
+}
+
+static void
+free_ttilist(txn_test_iter ***ttilist, size_t *tticnt)
+{
+ if (!ttilist || !*ttilist || !**ttilist) {
+ return;
+ }
+ while (*tticnt > 0) {
+ (*tticnt)--;
+ free_txn_test_iter((*ttilist)[*tticnt]);
+ }
+ slapi_ch_free((void *)ttilist);
+}
+
+static void
+init_ttilist(txn_test_iter **ttilist, size_t tticnt)
+{
+ if (!ttilist || !*ttilist) {
+ return;
+ }
+ while (tticnt > 0) {
+ tticnt--;
+ init_txn_test_iter(ttilist[tticnt]);
+ }
+}
+
+static void
+print_ttilist(txn_test_iter **ttilist, size_t tticnt)
+{
+ while (tticnt > 0) {
+ tticnt--;
+ LDAPDebug2Args(LDAP_DEBUG_ANY,
+ "txn_test_threadmain: attr [%s] cnt [%lu]\n",
+ ttilist[tticnt]->attr, ttilist[tticnt]->cnt);
+ }
+}
+
+#define TXN_TEST_IDX_OK_IF_NULL "nscpEntryDN"
+
+static void
+txn_test_init_cfg(txn_test_cfg *cfg)
+{
+ static char *indexlist = "aci,entryrdn,numsubordinates,uid,ancestorid,objectclass,uniquemember,cn,parentid,nsuniqueid,sn,id2entry," TXN_TEST_IDX_OK_IF_NULL;
+ char *indexlist_copy = NULL;
+
+ cfg->hold_msec = getenv(TXN_TEST_HOLD_MSEC) ? atoi(getenv(TXN_TEST_HOLD_MSEC)) : 200;
+ cfg->loop_msec = getenv(TXN_TEST_LOOP_MSEC) ? atoi(getenv(TXN_TEST_LOOP_MSEC)) : 10;
+ cfg->flags = getenv(TXN_TEST_USE_RMW) ? DB_RMW : 0;
+ cfg->use_txn = getenv(TXN_TEST_USE_TXN) ? 1 : 0;
+ if (getenv(TXN_TEST_INDEXES)) {
+ indexlist_copy = slapi_ch_strdup(getenv(TXN_TEST_INDEXES));
+ } else {
+ indexlist_copy = slapi_ch_strdup(indexlist);
+ }
+ cfg->indexes = slapi_str2charray(indexlist_copy, ",");
+ slapi_ch_free_string(&indexlist_copy);
+ cfg->verbose = getenv(TXN_TEST_VERBOSE) ? 1 : 0;
+
+ slapi_log_error(SLAPI_LOG_FATAL, "txn_test_threadmain",
+ "Config hold_msec [%d] loop_msec [%d] rmw [%d] txn [%d] indexes [%s]\n",
+ cfg->hold_msec, cfg->loop_msec, cfg->flags, cfg->use_txn,
+ getenv(TXN_TEST_INDEXES) ? getenv(TXN_TEST_INDEXES) : indexlist);
+}
+
+static int txn_test_threadmain(void *param)
+{
+ dblayer_private *priv = NULL;
+ struct ldbminfo *li = NULL;
+ Object *inst_obj;
+ int rc = 0;
+ txn_test_iter **ttilist = NULL;
+ size_t tticnt = 0;
+ DB_TXN *txn = NULL;
+ txn_test_cfg cfg;
+ size_t counter = 0;
+ char keybuf[8192];
+ char databuf[8192];
+
+ PR_ASSERT(NULL != param);
+ li = (struct ldbminfo*)param;
+
+ priv = (dblayer_private*)li->li_dblayer_private;
+ PR_ASSERT(NULL != priv);
+
+ INCR_THREAD_COUNT(priv);
+
+ if (!priv->dblayer_enable_transactions) {
+ goto end;
+ }
+
+ txn_test_init_cfg(&cfg);
+
+wait_for_init:
+ free_ttilist(&ttilist, &tticnt);
+ DS_Sleep(PR_MillisecondsToInterval(1000));
+ if (priv->dblayer_stop_threads) {
+ goto end;
+ }
+
+ for (inst_obj = objset_first_obj(li->li_instance_set); inst_obj;
+ inst_obj = objset_next_obj(li->li_instance_set, inst_obj)) {
+ char **idx = NULL;
+ ldbm_instance *inst = (ldbm_instance *)object_get_data(inst_obj);
+ backend *be = inst->inst_be;
+
+ if (be->be_state != BE_STATE_STARTED) {
+ object_release(inst_obj);
+ goto wait_for_init;
+ }
+
+ for (idx = cfg.indexes; idx && *idx; ++idx) {
+ DB *db = NULL;
+ if (be->be_state != BE_STATE_STARTED) {
+ object_release(inst_obj);
+ goto wait_for_init;
+ }
+
+ if (!strcmp(*idx, "id2entry")) {
+ dblayer_get_id2entry(be, &db);
+ if (db == NULL) {
+ object_release(inst_obj);
+ goto wait_for_init;
+ }
+ } else {
+ struct attrinfo *ai = NULL;
+ ainfo_get(be, *idx, &ai);
+ if (NULL == ai) {
+ object_release(inst_obj);
+ goto wait_for_init;
+ }
+ dblayer_get_index_file(be, ai, &db, 0);
+ if (NULL == db) {
+ if (strcasecmp(*idx, TXN_TEST_IDX_OK_IF_NULL)) {
+ object_release(inst_obj);
+ goto wait_for_init;
+ }
+ }
+ }
+ if (db) {
+ ttilist = (txn_test_iter **)slapi_ch_realloc((char *)ttilist, sizeof(txn_test_iter *) * (tticnt + 1));
+ ttilist[tticnt++] = new_txn_test_iter(db, *idx, be, cfg.flags);
+ }
+ }
+ }
+
+ while (!priv->dblayer_stop_threads) {
+retry_txn:
+ init_ttilist(ttilist, tticnt);
+ if (txn) {
+ TXN_ABORT(txn);
+ txn = NULL;
+ }
+ if (cfg.use_txn) {
+ rc = TXN_BEGIN(priv->dblayer_env->dblayer_DB_ENV, NULL, &txn, 0);
+ if (rc || !txn) {
+ LDAPDebug2Args(LDAP_DEBUG_ANY,
+ "txn_test_threadmain failed to create a new transaction, err=%d (%s)\n",
+ rc, dblayer_strerror(rc));
+ }
+ } else {
+ rc = 0;
+ }
+ if (!rc) {
+ DBT key;
+ DBT data;
+ size_t ii;
+ size_t donecnt = 0;
+ size_t cnt = 0;
+
+ /* phase 1 - open a cursor to each db */
+ if (cfg.verbose) {
+ LDAPDebug1Arg(LDAP_DEBUG_ANY,
+ "txn_test_threadmain: starting [%lu] indexes\n", tticnt);
+ }
+ for (ii = 0; ii < tticnt; ++ii) {
+ txn_test_iter *tti = ttilist[ii];
+
+retry_cursor:
+ if (priv->dblayer_stop_threads) {
+ goto end;
+ }
+ if (tti->be->be_state != BE_STATE_STARTED) {
+ if (txn) {
+ TXN_ABORT(txn);
+ txn = NULL;
+ }
+ goto wait_for_init;
+ }
+ if (tti->db->open_flags == 0xdbdbdbdb) {
+ if (txn) {
+ TXN_ABORT(txn);
+ txn = NULL;
+ }
+ goto wait_for_init;
+ }
+ rc = tti->db->cursor(tti->db, txn, &tti->cur, 0);
+ if (DB_LOCK_DEADLOCK == rc) {
+ if (cfg.verbose) {
+ LDAPDebug0Args(LDAP_DEBUG_ANY,
+ "txn_test_threadmain cursor create deadlock - retry\n");
+ }
+ if (cfg.use_txn) {
+ goto retry_txn;
+ } else {
+ goto retry_cursor;
+ }
+ } else if (rc) {
+ LDAPDebug2Args(LDAP_DEBUG_ANY,
+ "txn_test_threadmain failed to create a new cursor, err=%d (%s)\n",
+ rc, dblayer_strerror(rc));
+ }
+ }
+
+ memset(&key, 0, sizeof(key));
+ key.flags = DB_DBT_USERMEM;
+ key.data = keybuf;
+ key.ulen = sizeof(keybuf);
+ memset(&data, 0, sizeof(data));
+ data.flags = DB_DBT_USERMEM;
+ data.data = databuf;
+ data.ulen = sizeof(databuf);
+ /* phase 2 - iterate over each cursor at the same time until
+ 1) get error
+ 2) get deadlock
+ 3) all cursors are exhausted
+ */
+ while (donecnt < tticnt) {
+ for (ii = 0; ii < tticnt; ++ii) {
+ txn_test_iter *tti = ttilist[ii];
+ if (tti->cur) {
+retry_get:
+ if (priv->dblayer_stop_threads) {
+ goto end;
+ }
+ if (tti->be->be_state != BE_STATE_STARTED) {
+ if (txn) {
+ TXN_ABORT(txn);
+ txn = NULL;
+ }
+ goto wait_for_init;
+ }
+ if (tti->db->open_flags == 0xdbdbdbdb) {
+ if (txn) {
+ TXN_ABORT(txn);
+ txn = NULL;
+ }
+ goto wait_for_init;
+ }
+ rc = tti->cur->c_get(tti->cur, &key, &data, tti->flags);
+ if (DB_LOCK_DEADLOCK == rc) {
+ if (cfg.verbose) {
+ LDAPDebug0Args(LDAP_DEBUG_ANY,
+ "txn_test_threadmain cursor get deadlock - retry\n");
+ }
+ if (cfg.use_txn) {
+ goto retry_txn;
+ } else {
+ goto retry_get;
+ }
+ } else if (DB_NOTFOUND == rc) {
+ donecnt++; /* ran out of this one */
+ tti->flags = DB_FIRST|cfg.flags; /* start over until all indexes are done */
+ } else if (rc) {
+ if ((DB_BUFFER_SMALL != rc) || cfg.verbose) {
+ LDAPDebug2Args(LDAP_DEBUG_ANY,
+ "txn_test_threadmain failed to read a cursor, err=%d (%s)\n",
+ rc, dblayer_strerror(rc));
+ }
+ tti->cur->c_close(tti->cur);
+ tti->cur = NULL;
+ donecnt++;
+ } else {
+ tti->cnt++;
+ tti->flags = default_flags|cfg.flags;
+ cnt++;
+ }
+ }
+ }
+ }
+ TXN_TEST_PAGE_HOLD(cfg.hold_msec);
+ /*print_ttilist(ttilist, tticnt);*/
+ init_ttilist(ttilist, tticnt);
+ if (cfg.verbose) {
+ LDAPDebug2Args(LDAP_DEBUG_ANY,
+ "txn_test_threadmain: finished [%lu] indexes [%lu] records\n", tticnt, cnt);
+ }
+ TXN_TEST_LOOP_WAIT(cfg.loop_msec);
+ } else {
+ TXN_TEST_LOOP_WAIT(cfg.loop_msec);
+ }
+ counter++;
+ if (!(counter % 40)) {
+ /* some operations get completely stuck - so every once in a while,
+ pause to allow those ops to go through */
+ DS_Sleep(PR_SecondsToInterval(1));
+ }
+ }
+
+end:
+ slapi_ch_array_free(cfg.indexes);
+ free_ttilist(&ttilist, &tticnt);
+ if (txn) {
+ TXN_ABORT(txn);
+ }
+ DECR_THREAD_COUNT(priv);
+ return 0;
+}
+
+/*
+ * create a thread for transaction deadlock testing
+ */
+static int
+dblayer_start_txn_test_thread(struct ldbminfo *li)
+{
+ int return_value = 0;
+ if (NULL == PR_CreateThread (PR_USER_THREAD,
+ (VFP) (void *) txn_test_threadmain, li,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ SLAPD_DEFAULT_THREAD_STACKSIZE) )
+ {
+ PRErrorCode prerr = PR_GetError();
+ LDAPDebug(LDAP_DEBUG_ANY, "failed to create txn test thread, "
+ SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
+ prerr, slapd_pr_strerror(prerr), 0);
+ return_value = -1;
+ }
+ return return_value;
+}
+
/* deadlock thread main function */
static int deadlock_threadmain(void *param)
diff --git a/ldap/servers/slapd/back-ldbm/index.c b/ldap/servers/slapd/back-ldbm/index.c
index 7e8aa12..cfcd51f 100644
--- a/ldap/servers/slapd/back-ldbm/index.c
+++ b/ldap/servers/slapd/back-ldbm/index.c
@@ -412,7 +412,7 @@ index_addordel_entry(
}
result = index_addordel_string(be, SLAPI_ATTR_NSCP_ENTRYDN, slapi_sdn_get_ndn(&parent), e->ep_id, flags, txn);
if ( result != 0 ) {
- ldbm_nasty(errmsg, 1020, result);
+ ldbm_nasty(errmsg, 1021, result);
return( result );
}
slapi_sdn_done(&parent);
@@ -423,6 +423,7 @@ index_addordel_entry(
*/
result = entryrdn_index_entry(be, e, flags, txn);
if ( result != 0 ) {
+ ldbm_nasty(errmsg, 1023, result);
return( result );
}
/* To maintain tombstonenumsubordinates,
@@ -433,7 +434,7 @@ index_addordel_entry(
result = index_addordel_values_sv(be, LDBM_PARENTID_STR, svals, NULL,
e->ep_id, flags, txn);
if ( result != 0 ) {
- ldbm_nasty(errmsg, 1020, result);
+ ldbm_nasty(errmsg, 1022, result);
return( result );
}
}
@@ -481,6 +482,7 @@ index_addordel_entry(
if (entryrdn_get_switch()) { /* subtree-rename: on */
result = entryrdn_index_entry(be, e, flags, txn);
if ( result != 0 ) {
+ ldbm_nasty(errmsg, 1031, result);
return( result );
}
}
@@ -608,13 +610,18 @@ index_add_mods(
/* We need to first remove the old values from the
* index, if any. */
if (deleted_valueArray) {
- index_addordel_values_sv( be, mods[i]->mod_type,
- deleted_valueArray, evals, id,
- flags, txn );
+ rc = index_addordel_values_sv( be, mods[i]->mod_type,
+ deleted_valueArray, evals, id,
+ flags, txn );
+ if (rc) {
+ ldbm_nasty(errmsg, 1041, rc);
+ goto error;
+ }
}
/* Free valuearray */
slapi_valueset_free(mod_vals);
+ mod_vals = NULL;
case LDAP_MOD_ADD:
if ( mods_valueArray == NULL ) {
rc = 0;
@@ -643,9 +650,13 @@ index_add_mods(
}
if (mods_valueArray) {
rc = index_addordel_values_sv( be,
- mods[i]->mod_type,
- mods_valueArray, NULL,
- id, BE_INDEX_ADD, txn );
+ mods[i]->mod_type,
+ mods_valueArray, NULL,
+ id, BE_INDEX_ADD, txn );
+ if (rc) {
+ ldbm_nasty(errmsg, 1042, rc);
+ goto error;
+ }
} else {
rc = 0;
}
@@ -702,12 +713,17 @@ index_add_mods(
/* Update the index, if necessary */
if (deleted_valueArray) {
- index_addordel_values_sv( be, mods[i]->mod_type,
- deleted_valueArray, evals, id,
- flags, txn );
+ rc = index_addordel_values_sv( be, mods[i]->mod_type,
+ deleted_valueArray, evals, id,
+ flags, txn );
+ if (rc) {
+ ldbm_nasty(errmsg, 1043, rc);
+ goto error;
+ }
}
slapi_valueset_free(mod_vals);
+ mod_vals = NULL;
} else {
/* determine if the presence key should be
@@ -753,15 +769,25 @@ index_add_mods(
rc = index_addordel_values_sv( be, basetype,
mods_valueArray,
evals, id, flags, txn );
+ if (rc) {
+ ldbm_nasty(errmsg, 1044, rc);
+ goto error;
+ }
}
rc = 0;
break;
} /* switch ( mods[i]->mod_op & ~LDAP_MOD_BVALUES ) */
+error:
/* free memory */
slapi_ch_free((void **)&tmp);
+ tmp = NULL;
valuearray_free(&mods_valueArray);
+ mods_valueArray = NULL;
slapi_valueset_free(all_vals);
+ all_vals = NULL;
+ slapi_valueset_free(mod_vals);
+ mod_vals = NULL;
if ( rc != 0 ) {
ldbm_nasty(errmsg, 1040, rc);
@@ -996,6 +1022,9 @@ index_read_ext_allids(
idl = idl_fetch_ext( be, db, &key, db_txn, ai, err, allidslimit );
if(*err == DB_LOCK_DEADLOCK) {
ldbm_nasty("index read retrying transaction", 1045, *err);
+#ifdef FIX_TXN_DEADLOCKS
+#error can only retry here if txn == NULL - otherwise, have to abort and retry txn
+#endif
continue;
} else {
break;
@@ -1124,6 +1153,9 @@ retry:
cursor->c_close(cursor);
cursor = NULL;
key->data = saved_key;
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to abort and retry the transaction, not just the cursor
+#endif
goto retry;
} else
{
@@ -1146,6 +1178,9 @@ retry:
cursor->c_close(cursor);
cursor = NULL;
key->data = saved_key;
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to abort and retry the transaction, not just the cursor
+#endif
goto retry;
}
error:
@@ -1493,6 +1528,9 @@ index_range_read_ext(
tmp = idl_fetch_ext( be, db, &cur_key, NULL, ai, err, allidslimit );
if(*err == DB_LOCK_DEADLOCK) {
ldbm_nasty("index_range_read retrying transaction", 1090, *err);
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to abort and retry the transaction, not just the fetch
+#endif
continue;
} else {
break;
@@ -1641,7 +1679,7 @@ addordel_values(
if ( rc != 0)
{
- ldbm_nasty(errmsg, 1090, rc);
+ ldbm_nasty(errmsg, 1096, rc);
}
index_free_prefix (prefix);
if (NULL != key.dptr && prefix != key.dptr)
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c
index 1539c7c..18390c2 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c
@@ -934,7 +934,7 @@ ldbm_back_add( Slapi_PBlock *pb )
if (retry_count == RETRY_TIMES) {
/* Failed */
LDAPDebug( LDAP_DEBUG_ANY, "Retry count exceeded in add\n", 0, 0, 0 );
- ldap_result_code= LDAP_OPERATIONS_ERROR;
+ ldap_result_code= LDAP_BUSY;
goto error_return;
}
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
index 57a4605..237085c 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
@@ -60,7 +60,8 @@ ldbm_back_delete( Slapi_PBlock *pb )
struct ldbminfo *li = NULL;
struct backentry *e = NULL;
struct backentry *tombstone = NULL;
- struct backentry *original_entry = NULL;
+ Slapi_Entry *original_entry = NULL;
+ struct backentry *original_tombstone = NULL;
char *dn = NULL;
back_txn txn;
back_txnid parent_txn;
@@ -90,7 +91,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
int delete_tombstone_entry = 0; /* We must remove the given tombstone entry from the DB */
int create_tombstone_entry = 0; /* We perform a "regular" LDAP delete but since we use */
/* replication, we must create a new tombstone entry */
- int e_in_cache = 0;
int tombstone_in_cache = 0;
entry_address *addr;
int addordel_flags = 0; /* passed to index_addordel */
@@ -98,6 +98,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
Slapi_Entry *orig_entry = NULL;
Slapi_DN parentsdn;
int opreturn = 0;
+ int free_delete_existing_entry = 0;
slapi_pblock_get( pb, SLAPI_BACKEND, &be);
slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
@@ -186,7 +187,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
/* retval is -1 */
goto error_return; /* error result sent by find_entry2modify() */
}
- e_in_cache = 1;
if ( slapi_entry_has_children( e->ep_entry ) )
{
@@ -206,6 +206,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
*/
ldap_result_code= get_copy_of_entry(pb, addr, &txn,
SLAPI_DELETE_EXISTING_ENTRY, !is_replicated_operation);
+ free_delete_existing_entry = 1;
if(ldap_result_code==LDAP_OPERATIONS_ERROR ||
ldap_result_code==LDAP_INVALID_DN_SYNTAX)
{
@@ -428,6 +429,11 @@ ldbm_back_delete( Slapi_PBlock *pb )
slapi_value_free(&tomb_value);
/* XXXggood above used to be: slapi_entry_add_string(tombstone->ep_entry, SLAPI_ATTR_OBJECTCLASS, SLAPI_ATTR_VALUE_TOMBSTONE); */
/* JCMREPL - Add a description of what's going on? */
+
+ if ( (original_tombstone = backentry_dup( tombstone )) == NULL ) {
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ goto error_return;
+ }
}
if (!is_ruv && !is_fixup_operation && !delete_tombstone_entry) {
@@ -443,7 +449,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
}
}
- if ( (original_entry = backentry_dup( e )) == NULL ) {
+ if ( (original_entry = slapi_entry_dup( e->ep_entry )) == NULL ) {
ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
}
@@ -456,26 +462,45 @@ ldbm_back_delete( Slapi_PBlock *pb )
txn.back_txn_txn = NULL; /* ready to create the child transaction */
for (retry_count = 0; retry_count < RETRY_TIMES; retry_count++) {
if (txn.back_txn_txn && (txn.back_txn_txn != parent_txn)) {
+ Slapi_Entry *ent = NULL;
+
dblayer_txn_abort(li,&txn);
slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
- if (e_in_cache) {
- /* entry 'e' is in the entry cache. Since we reset 'e' to
- * the original_entry, remove it from the cache. */
- CACHE_REMOVE(&inst->inst_cache, e);
- cache_unlock_entry(&inst->inst_cache, e);
- CACHE_RETURN(&inst->inst_cache, &e);
- /* As we are about to delete it,
- * we don't put the entry back to cache */
- e_in_cache = 0;
- } else {
- backentry_free(&e);
+
+ /* reset original entry */
+ slapi_pblock_get( pb, SLAPI_DELETE_EXISTING_ENTRY, &ent );
+ if (ent && (ent != original_entry) && free_delete_existing_entry) {
+ slapi_entry_free(ent);
+ slapi_pblock_set( pb, SLAPI_DELETE_EXISTING_ENTRY, NULL );
}
- slapi_pblock_set( pb, SLAPI_DELETE_EXISTING_ENTRY, original_entry->ep_entry );
- e = original_entry;
- if ( (original_entry = backentry_dup( e )) == NULL ) {
+ slapi_entry_free(e->ep_entry);
+ e->ep_entry = original_entry;
+ if ( (original_entry = slapi_entry_dup( e->ep_entry )) == NULL ) {
ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
}
+ slapi_pblock_set( pb, SLAPI_DELETE_EXISTING_ENTRY, original_entry );
+ free_delete_existing_entry = 0; /* owned by original_entry now */
+ if (nscpEntrySDN) {
+ nscpEntrySDN = slapi_entry_get_sdn(original_entry);
+ }
+
+ /* reset tombstone entry */
+ if (original_tombstone) {
+ if (tombstone_in_cache) {
+ CACHE_REMOVE(&inst->inst_cache, tombstone);
+ CACHE_RETURN(&inst->inst_cache, &tombstone);
+ tombstone_in_cache = 0;
+ } else {
+ backentry_free(&tombstone);
+ }
+ tombstone = original_tombstone;
+ if ( (original_tombstone = backentry_dup( tombstone )) == NULL ) {
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ goto error_return;
+ }
+ }
+
/* We're re-trying */
LDAPDebug0Args(LDAP_DEBUG_BACKLDBM,
"Delete Retrying Transaction\n");
@@ -562,6 +587,14 @@ ldbm_back_delete( Slapi_PBlock *pb )
* tentatively for now, then cache_add again when the original
* entry is removed from the cache.
*/
+ if (cache_add_tentative( &inst->inst_cache, tombstone, NULL) == 0) {
+ tombstone_in_cache = 1;
+ } else if (!(tombstone->ep_state & ENTRY_STATE_NOTINCACHE)) {
+ LDAPDebug1Arg(LDAP_DEBUG_CACHE,
+ "id2entry_add tombstone (%s) is in cache\n",
+ slapi_entry_get_dn(tombstone->ep_entry));
+ tombstone_in_cache = 1;
+ }
retval = id2entry_add( be, tombstone, &txn );
if (DB_LOCK_DEADLOCK == retval) {
LDAPDebug( LDAP_DEBUG_ARGS, "delete 1 DB_LOCK_DEADLOCK\n", 0, 0, 0 );
@@ -576,14 +609,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
LDAP_OPERATIONS_ERROR, retry_count);
goto error_return;
}
- if (cache_add_tentative( &inst->inst_cache, tombstone, NULL) == 0) {
- tombstone_in_cache = 1;
- } else if (!(tombstone->ep_state & ENTRY_STATE_NOTINCACHE)) {
- LDAPDebug1Arg(LDAP_DEBUG_CACHE,
- "id2entry_add tombstone (%s) is in cache\n",
- slapi_entry_get_dn(tombstone->ep_entry));
- tombstone_in_cache = 1;
- }
}
else
{
@@ -966,7 +991,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
if (retry_count == RETRY_TIMES) {
/* Failed */
LDAPDebug( LDAP_DEBUG_ANY, "Retry count exceeded in delete\n", 0, 0, 0 );
- ldap_result_code= LDAP_OPERATIONS_ERROR;
+ ldap_result_code= LDAP_BUSY;
retval = -1;
goto error_return;
}
@@ -1007,18 +1032,13 @@ ldbm_back_delete( Slapi_PBlock *pb )
}
/* delete from cache and clean up */
- if (e_in_cache) {
+ if (e) {
CACHE_REMOVE(&inst->inst_cache, e);
cache_unlock_entry(&inst->inst_cache, e);
CACHE_RETURN(&inst->inst_cache, &e);
+ e = NULL;
}
- if (tombstone_in_cache) {
- if (CACHE_ADD( &inst->inst_cache, tombstone, NULL ) == 0) {
- tombstone_in_cache = 1;
- } else {
- tombstone_in_cache = 0;
- }
- }
+
if (parent_found)
{
/* Replace the old parent entry with the newly modified one */
@@ -1042,6 +1062,9 @@ error_return:
if (tombstone_in_cache)
{
CACHE_REMOVE( &inst->inst_cache, tombstone );
+ CACHE_RETURN( &inst->inst_cache, &tombstone );
+ tombstone = NULL;
+ tombstone_in_cache = 0;
}
else
{
@@ -1108,6 +1131,8 @@ common_return:
if (tombstone_in_cache)
{
CACHE_RETURN( &inst->inst_cache, &tombstone );
+ tombstone = NULL;
+ tombstone_in_cache = 0;
}
else
{
@@ -1126,7 +1151,7 @@ common_return:
/* Need to return to cache after post op plugins are called */
if (retval) { /* error case */
- if (e && e_in_cache) {
+ if (e) {
cache_unlock_entry( &inst->inst_cache, e );
CACHE_RETURN( &inst->inst_cache, &e );
}
@@ -1156,8 +1181,13 @@ diskfull_return:
*/
slapi_pblock_set(pb, SLAPI_URP_NAMING_COLLISION_DN, slapi_ch_strdup (dn));
}
- done_with_pblock_entry(pb, SLAPI_DELETE_EXISTING_ENTRY);
- backentry_free(&original_entry);
+ if (free_delete_existing_entry) {
+ done_with_pblock_entry(pb, SLAPI_DELETE_EXISTING_ENTRY);
+ } else { /* owned by original_entry */
+ slapi_pblock_set(pb, SLAPI_DELETE_EXISTING_ENTRY, NULL);
+ }
+ slapi_entry_free(original_entry);
+ backentry_free(&original_tombstone);
slapi_ch_free((void**)&errbuf);
slapi_sdn_done(&sdn);
slapi_ch_free_string(&e_uniqueid);
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
index b548b29..449e02a 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
@@ -115,8 +115,8 @@ static char *_entryrdn_decrypt_key(backend *be, const char *key, struct attrinfo
#endif
static int _entryrdn_get_elem(DBC *cursor, DBT *key, DBT *data, const char *comp_key, rdn_elem **elem);
static int _entryrdn_get_tombstone_elem(DBC *cursor, Slapi_RDN *srdn, DBT *key, const char *comp_key, rdn_elem **elem);
-static int _entryrdn_put_data(DBC *cursor, DBT *key, DBT *data, char type);
-static int _entryrdn_del_data(DBC *cursor, DBT *key, DBT *data);
+static int _entryrdn_put_data(DBC *cursor, DBT *key, DBT *data, char type, DB_TXN *db_txn);
+static int _entryrdn_del_data(DBC *cursor, DBT *key, DBT *data, DB_TXN *db_txn);
static int _entryrdn_insert_key(backend *be, DBC *cursor, Slapi_RDN *srdn, ID id, DB_TXN *db_txn);
static int _entryrdn_insert_key_elems(backend *be, DBC *cursor, Slapi_RDN *srdn, DBT *key, rdn_elem *elem, rdn_elem *childelem, size_t childelemlen, DB_TXN *db_txn);
static int _entryrdn_delete_key(backend *be, DBC *cursor, Slapi_RDN *srdn, ID id, DB_TXN *db_txn);
@@ -274,7 +274,7 @@ entryrdn_index_entry(backend *be,
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_index_entry: Failed to make a cursor: %s(%d)\n",
dblayer_strerror(rc), rc);
- if (DB_LOCK_DEADLOCK == rc) {
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
@@ -284,6 +284,12 @@ entryrdn_index_entry(backend *be,
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "entryrdn_index_entry: cursor open failed after [%d] retries\n", db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ goto bail;
+ }
if (flags & BE_INDEX_ADD) {
rc = _entryrdn_insert_key(be, cursor, srdn, e->ep_id, db_txn);
@@ -303,7 +309,7 @@ bail:
slapi_log_error(ENTRYRDN_LOGLEVEL(myrc), ENTRYRDN_TAG,
"entryrdn_index_entry: Failed to close cursor: %s(%d)\n",
dblayer_strerror(myrc), myrc);
- if (DB_LOCK_DEADLOCK == myrc) {
+ if ((DB_LOCK_DEADLOCK == myrc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
@@ -317,6 +323,11 @@ bail:
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "entryrdn_index_entry: cursor close failed after [%d] retries\n", db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ }
}
if (db) {
dblayer_release_index_file(be, ai, db);
@@ -407,7 +418,7 @@ entryrdn_index_read_ext(backend *be,
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_index_read: Failed to make a cursor: %s(%d)\n",
dblayer_strerror(rc), rc);
- if (DB_LOCK_DEADLOCK == rc) {
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
@@ -417,6 +428,13 @@ entryrdn_index_read_ext(backend *be,
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "entryrdn_index_read: Failed to make a cursor after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ goto bail;
+ }
rc = _entryrdn_index_read(be, cursor, &srdn, &elem, NULL, NULL,
flags, db_txn);
@@ -434,7 +452,7 @@ bail:
slapi_log_error(ENTRYRDN_LOGLEVEL(myrc), ENTRYRDN_TAG,
"entryrdn_index_read: Failed to close cursor: %s(%d)\n",
dblayer_strerror(myrc), myrc);
- if (DB_LOCK_DEADLOCK == myrc) {
+ if ((DB_LOCK_DEADLOCK == myrc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
@@ -448,6 +466,12 @@ bail:
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "entryrdn_index_read: Failed to close cursor after [%d] retries\n",
+ db_retry);
+ rc = rc ? rc : DB_LOCK_DEADLOCK;
+ }
}
if (db) {
dblayer_release_index_file(be, ai, db);
@@ -594,7 +618,7 @@ entryrdn_rename_subtree(backend *be,
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_rename_subtree: Failed to make a cursor: %s(%d)\n",
dblayer_strerror(rc), rc);
- if (DB_LOCK_DEADLOCK == rc) {
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
@@ -604,6 +628,13 @@ entryrdn_rename_subtree(backend *be,
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "entryrdn_rename_subtree: create cursor failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ goto bail;
+ }
/* prepare the element for the newly renamed rdn, if any. */
if (mynewsrdn) {
@@ -680,7 +711,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.ulen = renamedata.size = targetelemlen;
renamedata.data = (void *)targetelem;
renamedata.flags = DB_DBT_USERMEM;
- rc = _entryrdn_del_data(cursor, &key, &renamedata);
+ rc = _entryrdn_del_data(cursor, &key, &renamedata, db_txn);
if (rc) {
goto bail;
}
@@ -697,7 +728,7 @@ entryrdn_rename_subtree(backend *be,
_entryrdn_rdn_elem_size(*cep);
renamedata.data = (void *)(*cep);
renamedata.flags = DB_DBT_USERMEM;
- rc = _entryrdn_del_data(cursor, &key, &renamedata);
+ rc = _entryrdn_del_data(cursor, &key, &renamedata, db_txn);
if (rc) {
goto bail;
}
@@ -715,7 +746,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.ulen = renamedata.size = newelemlen;
renamedata.data = (void *)newelem;
renamedata.flags = DB_DBT_USERMEM;
- rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_SELF);
+ rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_SELF, db_txn);
if (rc) {
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_rename_subtree: Adding %s failed; "
@@ -736,7 +767,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.data = (void *)(*cep);
renamedata.flags = DB_DBT_USERMEM;
rc = _entryrdn_put_data(cursor, &key,
- &renamedata, RDN_INDEX_CHILD);
+ &renamedata, RDN_INDEX_CHILD, db_txn);
if (rc) {
goto bail;
}
@@ -755,7 +786,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.ulen = renamedata.size = oldsupelemlen;
renamedata.data = (void *)oldsupelem;
renamedata.flags = DB_DBT_USERMEM;
- rc = _entryrdn_del_data(cursor, &key, &renamedata);
+ rc = _entryrdn_del_data(cursor, &key, &renamedata, db_txn);
if (rc) {
goto bail;
}
@@ -787,7 +818,7 @@ entryrdn_rename_subtree(backend *be,
goto bail;
}
}
- rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_PARENT);
+ rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_PARENT, db_txn);
if (rc) {
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_rename_subtree: Adding "
@@ -812,7 +843,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.ulen = renamedata.size = targetelemlen;
renamedata.data = (void *)targetelem;
renamedata.flags = DB_DBT_USERMEM;
- rc = _entryrdn_del_data(cursor, &key, &renamedata);
+ rc = _entryrdn_del_data(cursor, &key, &renamedata, db_txn);
if (rc) {
goto bail;
}
@@ -822,7 +853,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.ulen = renamedata.size = newelemlen;
renamedata.data = (void *)newelem;
renamedata.flags = DB_DBT_USERMEM;
- rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_SELF);
+ rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_SELF, db_txn);
if (rc) {
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_rename_subtree: Adding %s failed; "
@@ -846,7 +877,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.ulen = renamedata.size = targetelemlen;
renamedata.data = (void *)targetelem;
renamedata.flags = DB_DBT_USERMEM;
- rc = _entryrdn_del_data(cursor, &key, &renamedata);
+ rc = _entryrdn_del_data(cursor, &key, &renamedata, db_txn);
if (rc) {
goto bail;
}
@@ -881,7 +912,7 @@ entryrdn_rename_subtree(backend *be,
goto bail;
}
}
- rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_CHILD);
+ rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_CHILD, db_txn);
if (rc) {
goto bail;
}
@@ -911,7 +942,7 @@ bail:
slapi_log_error(ENTRYRDN_LOGLEVEL(myrc), ENTRYRDN_TAG,
"entryrdn_rename_subtree: Failed to close cursor: %s(%d)\n",
dblayer_strerror(myrc), myrc);
- if (DB_LOCK_DEADLOCK == myrc) {
+ if ((DB_LOCK_DEADLOCK == myrc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
@@ -925,6 +956,12 @@ bail:
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "entryrdn_rename_subtree: Failed to close cursor after [%d] retries.\n",
+ db_retry);
+ rc = rc ? rc : DB_LOCK_DEADLOCK;
+ }
}
if (db) {
dblayer_release_index_file(be, ai, db);
@@ -1017,7 +1054,7 @@ entryrdn_get_subordinates(backend *be,
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_get_subordinates: Failed to make a cursor: %s(%d)\n",
dblayer_strerror(rc), rc);
- if (DB_LOCK_DEADLOCK == rc) {
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
@@ -1027,6 +1064,13 @@ entryrdn_get_subordinates(backend *be,
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "entryrdn_get_subordinates: Failed to make a cursor after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ goto bail;
+ }
rc = _entryrdn_index_read(be, cursor, &srdn, &elem,
NULL, &childelems, 0/*flags*/, db_txn);
@@ -1076,7 +1120,7 @@ bail:
slapi_log_error(ENTRYRDN_LOGLEVEL(myrc), ENTRYRDN_TAG,
"entryrdn_get_subordinates: Failed to close cursor: %s(%d)\n",
dblayer_strerror(myrc), myrc);
- if (DB_LOCK_DEADLOCK == myrc) {
+ if ((DB_LOCK_DEADLOCK == myrc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
@@ -1090,6 +1134,14 @@ bail:
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "entryrdn_get_subordinates: Failed to close cursor after [%d] retries\n",
+ db_retry);
+ rc = rc ? rc : DB_LOCK_DEADLOCK;
+ goto bail;
+ }
+
}
if (db) {
dblayer_release_index_file(be, ai, db);
@@ -1159,6 +1211,9 @@ entryrdn_lookup_dn(backend *be,
"entryrdn_lookup_dn: Failed to make a cursor: %s(%d)\n",
dblayer_strerror(rc), rc);
if (DB_LOCK_DEADLOCK == rc) {
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
ENTRYRDN_DELAY;
continue;
}
@@ -1199,6 +1254,11 @@ retry_get0:
if (rc) {
if (DB_LOCK_DEADLOCK == rc) {
/* try again */
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "entryrdn_get_parent: cursor get deadlock\n");
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
goto retry_get0;
} else if (DB_NOTFOUND == rc) { /* could be a suffix or
note: no parent for suffix */
@@ -1212,6 +1272,11 @@ retry_get1:
if (rc) {
if (DB_LOCK_DEADLOCK == rc) {
/* try again */
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "entryrdn_get_parent: retry cursor get deadlock\n");
goto retry_get1;
} else if (DB_NOTFOUND != rc) {
_entryrdn_cursor_print_error("entryrdn_lookup_dn",
@@ -1264,6 +1329,9 @@ bail:
"entryrdn_lookup_dn: Failed to close cursor: %s(%d)\n",
dblayer_strerror(myrc), myrc);
if (DB_LOCK_DEADLOCK == myrc) {
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
ENTRYRDN_DELAY;
continue;
}
@@ -1352,6 +1420,9 @@ entryrdn_get_parent(backend *be,
"entryrdn_get_parent: Failed to make a cursor: %s(%d)\n",
dblayer_strerror(rc), rc);
if (DB_LOCK_DEADLOCK == rc) {
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
ENTRYRDN_DELAY;
continue;
}
@@ -1388,6 +1459,11 @@ retry_get0:
rc = cursor->c_get(cursor, &key, &data, DB_SET);
if (rc) {
if (DB_LOCK_DEADLOCK == rc) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "entryrdn_get_parent: cursor get deadlock\n");
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
/* try again */
goto retry_get0;
} else if (DB_NOTFOUND == rc) { /* could be a suffix
@@ -1402,6 +1478,11 @@ retry_get1:
if (rc) {
if (DB_LOCK_DEADLOCK == rc) {
/* try again */
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "entryrdn_get_parent: retry cursor get deadlock\n");
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
goto retry_get1;
} else if (DB_NOTFOUND != rc) {
_entryrdn_cursor_print_error("entryrdn_get_parent",
@@ -1434,6 +1515,9 @@ bail:
"entryrdn_get_parent: Failed to close cursor: %s(%d)\n",
dblayer_strerror(myrc), myrc);
if (DB_LOCK_DEADLOCK == myrc) {
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
ENTRYRDN_DELAY;
continue;
}
@@ -1705,7 +1789,12 @@ retry_get:
*elem = (rdn_elem *)data->data;
if (rc) {
if (DB_LOCK_DEADLOCK == rc) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_get_elem: cursor get deadlock\n");
/* try again */
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
goto retry_get;
} else if (DB_BUFFER_SMALL == rc) {
/* try again */
@@ -1774,6 +1863,11 @@ retry_get0:
rc = cursor->c_get(cursor, key, &data, DB_SET|DB_MULTIPLE);
if (DB_LOCK_DEADLOCK == rc) {
/* try again */
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_get_tombstone_elem: cursor get deadlock\n");
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
goto retry_get0;
} else if (DB_NOTFOUND == rc) {
rc = 0; /* Child not found is ok */
@@ -1824,6 +1918,11 @@ retry_get1:
rc = cursor->c_get(cursor, key, &data, DB_NEXT_DUP|DB_MULTIPLE);
if (DB_LOCK_DEADLOCK == rc) {
/* try again */
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_get_tombstone_elem: retry cursor get deadlock\n");
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
goto retry_get1;
} else if (DB_NOTFOUND == rc) {
rc = 0;
@@ -1842,7 +1941,7 @@ bail:
}
static int
-_entryrdn_put_data(DBC *cursor, DBT *key, DBT *data, char type)
+_entryrdn_put_data(DBC *cursor, DBT *key, DBT *data, char type, DB_TXN *db_txn)
{
int rc = -1;
int db_retry = 0;
@@ -1866,6 +1965,8 @@ _entryrdn_put_data(DBC *cursor, DBT *key, DBT *data, char type)
"_entryrdn_put_data: The same key (%s) and the "
"data exists in index\n",
(char *)key->data);
+ rc = 0;
+ break;
} else {
char *keyword = NULL;
if (type == RDN_INDEX_CHILD) {
@@ -1879,7 +1980,7 @@ _entryrdn_put_data(DBC *cursor, DBT *key, DBT *data, char type)
"_entryrdn_put_data: Adding the %s link (%s) "
"failed: %s (%d)\n", keyword, (char *)key->data,
dblayer_strerror(rc), rc);
- if (DB_LOCK_DEADLOCK == rc) {
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
@@ -1889,13 +1990,19 @@ _entryrdn_put_data(DBC *cursor, DBT *key, DBT *data, char type)
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "_entryrdn_put_data: cursor put operation failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ }
bail:
slapi_log_error(SLAPI_LOG_TRACE, ENTRYRDN_TAG, "<-- _entryrdn_put_data\n");
return rc;
}
static int
-_entryrdn_del_data(DBC *cursor, DBT *key, DBT *data)
+_entryrdn_del_data(DBC *cursor, DBT *key, DBT *data, DB_TXN *db_txn)
{
int rc = -1;
int db_retry = 0;
@@ -1909,37 +2016,57 @@ _entryrdn_del_data(DBC *cursor, DBT *key, DBT *data)
NULL==data?"data":"unknown");
goto bail;
}
-retry_get:
- rc = cursor->c_get(cursor, key, data, DB_GET_BOTH);
- if (rc) {
- if (DB_LOCK_DEADLOCK == rc) {
- /* try again */
- goto retry_get;
- } else if (DB_NOTFOUND == rc) {
- rc = 0; /* not found is ok */
- } else {
- _entryrdn_cursor_print_error("_entryrdn_del_data",
- key->data, data->size, data->ulen, rc);
- }
- } else {
- /* We found it, so delete it */
- for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
- rc = cursor->c_del(cursor, 0);
- if (rc) {
+
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = cursor->c_get(cursor, key, data, DB_GET_BOTH);
+ if (rc) {
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
- "_entryrdn_del_data: Deleting %s failed; "
- "%s(%d)\n", (char *)key->data,
- dblayer_strerror(rc), rc);
- if (DB_LOCK_DEADLOCK == rc) {
- ENTRYRDN_DELAY;
- continue;
- }
+ "_entryrdn_del_data: cursor get deadlock\n");
+ /* try again */
+ } else if (DB_NOTFOUND == rc) {
+ rc = 0; /* not found is ok */
goto bail;
} else {
- break; /* success */
+ _entryrdn_cursor_print_error("_entryrdn_del_data",
+ key->data, data->size, data->ulen, rc);
+ goto bail;
+ }
+ } else {
+ break; /* found it */
+ }
+ }
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "_entryrdn_del_data: cursor get failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ goto bail;
+ }
+
+ /* We found it, so delete it */
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = cursor->c_del(cursor, 0);
+ if (rc) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_del_data: Deleting %s failed; "
+ "%s(%d)\n", (char *)key->data,
+ dblayer_strerror(rc), rc);
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
+ ENTRYRDN_DELAY;
+ continue;
}
+ goto bail;
+ } else {
+ break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "_entryrdn_del_data: cursor del failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ }
bail:
slapi_log_error(SLAPI_LOG_TRACE, ENTRYRDN_TAG,
"<-- _entryrdn_del_data\n");
@@ -1985,7 +2112,7 @@ _entryrdn_insert_key_elems(backend *be,
adddata.flags = DB_DBT_USERMEM;
/* adding RDN to the child key */
- rc = _entryrdn_put_data(cursor, key, &adddata, RDN_INDEX_CHILD);
+ rc = _entryrdn_put_data(cursor, key, &adddata, RDN_INDEX_CHILD, db_txn);
keybuf = key->data;
if (rc) { /* failed */
goto bail;
@@ -2002,7 +2129,7 @@ _entryrdn_insert_key_elems(backend *be,
key->size = key->ulen = strlen(keybuf) + 1;
key->flags = DB_DBT_USERMEM;
- rc = _entryrdn_put_data(cursor, key, &adddata, RDN_INDEX_SELF);
+ rc = _entryrdn_put_data(cursor, key, &adddata, RDN_INDEX_SELF, db_txn);
if (rc) { /* failed */
goto bail;
}
@@ -2022,7 +2149,7 @@ _entryrdn_insert_key_elems(backend *be,
adddata.data = (void *)parentelem;
adddata.flags = DB_DBT_USERMEM;
/* adding RDN to the self key */
- rc = _entryrdn_put_data(cursor, key, &adddata, RDN_INDEX_PARENT);
+ rc = _entryrdn_put_data(cursor, key, &adddata, RDN_INDEX_PARENT, db_txn);
/* Succeeded or failed, it's done. */
bail:
slapi_ch_free_string(&keybuf);
@@ -2036,7 +2163,7 @@ bail:
*/
static int
_entryrdn_replace_suffix_id(DBC *cursor, DBT *key, DBT *adddata,
- ID id, const char *normsuffix)
+ ID id, const char *normsuffix, DB_TXN *db_txn)
{
int rc = 0;
char *keybuf = NULL;
@@ -2061,7 +2188,7 @@ _entryrdn_replace_suffix_id(DBC *cursor, DBT *key, DBT *adddata,
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"_entryrdn_replace_suffix_id: Adding suffix %s failed: "
"%s (%d)\n", normsuffix, dblayer_strerror(rc), rc);
- if (DB_LOCK_DEADLOCK == rc) {
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
@@ -2070,6 +2197,13 @@ _entryrdn_replace_suffix_id(DBC *cursor, DBT *key, DBT *adddata,
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "_entryrdn_replace_suffix_id: cursor put failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ goto bail;
+ }
/*
* Fixing Child link:
@@ -2095,18 +2229,27 @@ _entryrdn_replace_suffix_id(DBC *cursor, DBT *key, DBT *adddata,
memset(&moddata, 0, sizeof(moddata));
moddata.flags = DB_DBT_USERMEM;
-retry_get0:
- rc = cursor->c_get(cursor, key, &data, DB_SET|DB_MULTIPLE);
- if (DB_LOCK_DEADLOCK == rc) {
- /* try again */
- goto retry_get0;
- } else if (DB_NOTFOUND == rc) {
- _entryrdn_cursor_print_error("_entryrdn_replace_suffix_id",
- key->data, data.size, data.ulen, rc);
- goto bail;
- } else if (rc) {
- _entryrdn_cursor_print_error("_entryrdn_replace_suffix_id",
- key->data, data.size, data.ulen, rc);
+
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = cursor->c_get(cursor, key, &data, DB_SET|DB_MULTIPLE);
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_replace_suffix_id: cursor get deadlock\n");
+ /* try again */
+ ENTRYRDN_DELAY;
+ } else if (rc) {
+ _entryrdn_cursor_print_error("_entryrdn_replace_suffix_id",
+ key->data, data.size, data.ulen, rc);
+ goto bail;
+ } else {
+ break; /* found */
+ }
+ }
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "_entryrdn_replace_suffix_id: cursor get1 failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
goto bail;
}
childelems = (rdn_elem **)slapi_ch_calloc(childnum, sizeof(rdn_elem *));
@@ -2124,13 +2267,16 @@ retry_get0:
moddata.data = childelem;
moddata.ulen = moddata.size = _entryrdn_rdn_elem_size(childelem);
/* Delete it first */
- rc = _entryrdn_del_data(cursor, key, &moddata);
+ rc = _entryrdn_del_data(cursor, key, &moddata, db_txn);
if (rc) {
goto bail0;
}
/* Add it back */
rc = _entryrdn_put_data(cursor, &realkey, &moddata,
- RDN_INDEX_CHILD);
+ RDN_INDEX_CHILD, db_txn);
+ if (rc) {
+ goto bail0;
+ }
if (curr_childnum + 1 == childnum) {
childnum *= 2;
childelems = (rdn_elem **)slapi_ch_realloc((char *)childelems,
@@ -2142,19 +2288,33 @@ retry_get0:
/* We don't access the address with this variable any more */
childelem = NULL;
} while (NULL != dataret.data && NULL != ptr);
-retry_get1:
- rc = cursor->c_get(cursor, key, &data, DB_NEXT_DUP|DB_MULTIPLE);
- if (DB_LOCK_DEADLOCK == rc) {
- /* try again */
- goto retry_get1;
- } else if (DB_NOTFOUND == rc) {
- rc = 0;
- break; /* done */
- } else if (rc) {
- _entryrdn_cursor_print_error("_entryrdn_replace_suffix_id",
- key->data, data.size, data.ulen, rc);
+
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = cursor->c_get(cursor, key, &data, DB_NEXT_DUP|DB_MULTIPLE);
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_replace_suffix_id: retry cursor get deadlock\n");
+ /* try again */
+ ENTRYRDN_DELAY;
+ } else if (!rc || (DB_NOTFOUND == rc)) {
+ break; /* done */
+ } else {
+ _entryrdn_cursor_print_error("_entryrdn_replace_suffix_id",
+ key->data, data.size, data.ulen, rc);
+ goto bail0;
+ }
+ }
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "_entryrdn_replace_suffix_id: cursor get2 failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
goto bail0;
}
+ if (DB_NOTFOUND == rc) {
+ rc = 0; /* ok */
+ break; /* we're done */
+ }
} while (0 == rc);
/*
@@ -2176,18 +2336,29 @@ retry_get1:
moddata.flags = DB_DBT_MALLOC;
/* Position cursor at the matching key */
-retry_get2:
- rc = cursor->c_get(cursor, key, &moddata, DB_SET);
- if (rc) {
- if (DB_LOCK_DEADLOCK == rc) {
- /* try again */
- goto retry_get2;
- } else if (rc) {
- _entryrdn_cursor_print_error("_entryrdn_replace_suffix_id",
- key->data, data.size, data.ulen, rc);
- goto bail0;
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = cursor->c_get(cursor, key, &moddata, DB_SET);
+ if (rc) {
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_replace_suffix_id: retry2 cursor get deadlock\n");
+ ENTRYRDN_DELAY;
+ } else {
+ _entryrdn_cursor_print_error("_entryrdn_replace_suffix_id",
+ key->data, data.size, data.ulen, rc);
+ goto bail0;
+ }
+ } else {
+ break;
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "_entryrdn_replace_suffix_id: cursor get3 failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ goto bail0;
+ }
pelem = (rdn_elem *)moddata.data;
if (TMPID == id_stored_to_internal(pelem->rdn_elem_id)) {
/* the parent id is TMPID;
@@ -2200,7 +2371,7 @@ retry_get2:
"_entryrdn_replace_suffix_id: "
"Fixing the parent link (%s) failed: %s (%d)\n",
keybuf, dblayer_strerror(rc), rc);
- if (DB_LOCK_DEADLOCK == rc) {
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
@@ -2209,6 +2380,13 @@ retry_get2:
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "_entryrdn_replace_suffix_id: cursor put failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ goto bail0;
+ }
}
slapi_ch_free((void **)&moddata.data);
} /* for (cep = childelems; cep && *cep; cep++) */
@@ -2220,6 +2398,9 @@ bail0:
bail:
slapi_ch_free_string(&keybuf);
slapi_ch_free_string(&realkeybuf);
+ if (moddata.data && (moddata.flags == DB_DBT_MALLOC)) {
+ slapi_ch_free((void **)&moddata.data);
+ }
return rc;
}
@@ -2294,7 +2475,7 @@ _entryrdn_insert_key(backend *be,
adddata.data = (void *)elem;
adddata.flags = DB_DBT_USERMEM;
- rc = _entryrdn_put_data(cursor, &key, &adddata, RDN_INDEX_SELF);
+ rc = _entryrdn_put_data(cursor, &key, &adddata, RDN_INDEX_SELF, db_txn);
if (DB_KEYEXIST == rc) {
DBT existdata;
rdn_elem *existelem = NULL;
@@ -2308,7 +2489,7 @@ _entryrdn_insert_key(backend *be,
"_entryrdn_insert_key: Get existing suffix %s "
"failed: %s (%d)\n",
nrdn, dblayer_strerror(rc), rc);
- if (DB_LOCK_DEADLOCK == rc) {
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
@@ -2317,12 +2498,19 @@ _entryrdn_insert_key(backend *be,
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_insert_key: cursor get failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ goto bail;
+ }
existelem = (rdn_elem *)existdata.data;
tmpid = id_stored_to_internal(existelem->rdn_elem_id);
slapi_ch_free((void **)&existelem);
if (TMPID == tmpid) {
rc = _entryrdn_replace_suffix_id(cursor, &key, &adddata,
- id, nrdn);
+ id, nrdn, db_txn);
if (rc) {
goto bail;
}
@@ -2401,10 +2589,13 @@ _entryrdn_insert_key(backend *be,
adddata.data = (void *)elem;
adddata.flags = DB_DBT_USERMEM;
- rc = _entryrdn_put_data(cursor, &key, &adddata, RDN_INDEX_SELF);
+ rc = _entryrdn_put_data(cursor, &key, &adddata, RDN_INDEX_SELF, db_txn);
slapi_log_error(SLAPI_LOG_BACKLDBM, ENTRYRDN_TAG,
"_entryrdn_insert_key: Suffix %s added: %d\n",
slapi_rdn_get_rdn(tmpsrdn), rc);
+#ifdef FIX_TXN_DEADLOCKS
+#error no checking for rc here? - what if rc is deadlock? should bail?
+#endif
} else {
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"_entryrdn_insert_key: Suffix \"%s\" not found: "
@@ -2651,25 +2842,41 @@ _entryrdn_delete_key(backend *be,
memset(&data, 0, sizeof(data));
data.flags = DB_DBT_MALLOC;
-retry_get0:
- rc = cursor->c_get(cursor, &key, &data, DB_SET);
- if (rc) {
- if (DB_LOCK_DEADLOCK == rc) {
- /* try again */
- goto retry_get0;
- } else if (DB_NOTFOUND != rc) {
- _entryrdn_cursor_print_error("_entryrdn_delete_key",
- key.data, data.size, data.ulen, rc);
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = cursor->c_get(cursor, &key, &data, DB_SET);
+ if (rc) {
+ if (DB_LOCK_DEADLOCK == rc) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_delete_key: cursor get deadlock\n");
+ /* try again */
+ if (db_txn) {
+ goto bail; /* have to abort/retry the entire transaction */
+ } else {
+ ENTRYRDN_DELAY; /* sleep for a bit then retry immediately */
+ }
+ } else if (DB_NOTFOUND != rc) {
+ _entryrdn_cursor_print_error("_entryrdn_delete_key",
+ key.data, data.size, data.ulen, rc);
+ goto bail;
+ } else {
+ break; /* DB_NOTFOUND - ok */
+ }
+ } else {
+ slapi_ch_free(&data.data);
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "_entryrdn_delete_key: Failed to remove %s; "
+ "has children\n", nrdn);
+ rc = -1;
goto bail;
}
- } else {
- slapi_ch_free(&data.data);
+ }
+ if (RETRY_TIMES == db_retry) {
slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
- "_entryrdn_delete_key: Failed to remove %s; "
- "has children\n", nrdn);
- rc = -1;
+ "_entryrdn_delete_key: failed after [%d] iterations\n", db_retry);
+ rc = DB_LOCK_DEADLOCK;
goto bail;
}
+
workid = id;
do {
@@ -2777,15 +2984,22 @@ retry_get0:
"_entryrdn_delete_key: Deleting %s failed; "
"%s(%d)\n", (char *)key.data,
dblayer_strerror(rc), rc);
- if (DB_LOCK_DEADLOCK == rc) {
- ENTRYRDN_DELAY;
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
+ ENTRYRDN_DELAY; /* sleep for a bit then retry immediately */
continue;
}
- goto bail;
+ goto bail; /* if deadlock and txn, have to abort entire txn */
} else {
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "_entryrdn_delete_key: delete parent link failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ goto bail;
+ }
} else if (parentnrdn) {
#ifdef LDAP_DEBUG_ENTRYRDN
_entryrdn_dump_rdn_elem(elem);
@@ -2800,15 +3014,22 @@ retry_get0:
"_entryrdn_delete_key: Deleting %s failed; "
"%s(%d)\n", (char *)key.data,
dblayer_strerror(rc), rc);
- if (DB_LOCK_DEADLOCK == rc) {
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
- goto bail;
+ goto bail; /* if deadlock and txn, have to abort entire txn */
} else {
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "_entryrdn_delete_key: delete parent's child link failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ goto bail;
+ }
selfnrdn = nrdn;
workid = id;
} else if (selfnrdn) {
@@ -2824,20 +3045,27 @@ retry_get0:
"_entryrdn_delete_key: Deleting %s failed; "
"%s(%d)\n", (char *)key.data,
dblayer_strerror(rc), rc);
- if (DB_LOCK_DEADLOCK == rc) {
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
- goto bail;
+ goto bail; /* if deadlock and txn, have to abort entire txn */
} else {
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "_entryrdn_delete_key: delete self link failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ }
goto bail; /* done */
}
} while (workid);
bail:
+ slapi_ch_free_string(&parentnrdn);
slapi_ch_free_string(&keybuf);
slapi_ch_free((void **)&elem);
slapi_log_error(SLAPI_LOG_TRACE, ENTRYRDN_TAG,
@@ -3107,6 +3335,11 @@ _entryrdn_index_read(backend *be,
retry_get0:
rc = cursor->c_get(cursor, &key, &data, DB_SET|DB_MULTIPLE);
if (DB_LOCK_DEADLOCK == rc) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_index_read: cursor get deadlock\n");
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
/* try again */
goto retry_get0;
} else if (DB_NOTFOUND == rc) {
@@ -3146,6 +3379,11 @@ retry_get0:
retry_get1:
rc = cursor->c_get(cursor, &key, &data, DB_NEXT_DUP|DB_MULTIPLE);
if (DB_LOCK_DEADLOCK == rc) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_index_read: retry cursor get deadlock\n");
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
/* try again */
goto retry_get1;
} else if (DB_NOTFOUND == rc) {
@@ -3197,7 +3435,12 @@ retry_get0:
rc = cursor->c_get(cursor, &key, &data, DB_SET|DB_MULTIPLE);
if (rc) {
if (DB_LOCK_DEADLOCK == rc) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_append_childidl: cursor get deadlock\n");
/* try again */
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
goto retry_get0;
} else if (DB_NOTFOUND == rc) {
rc = 0; /* okay not to have children */
@@ -3242,7 +3485,12 @@ retry_get1:
rc = cursor->c_get(cursor, &key, &data, DB_NEXT_DUP|DB_MULTIPLE);
if (rc) {
if (DB_LOCK_DEADLOCK == rc) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_append_childidl: retry cursor get deadlock\n");
/* try again */
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
goto retry_get1;
} else if (DB_NOTFOUND == rc) {
rc = 0; /* okay not to have children */
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
index bdc2967..f7520c6 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
@@ -460,25 +460,17 @@ ldbm_back_modify( Slapi_PBlock *pb )
/* New entry 'ec' is in the entry cache.
* Remove it from the cache once. */
CACHE_REMOVE(&inst->inst_cache, ec);
- cache_unlock_entry(&inst->inst_cache, e);
- CACHE_RETURN(&inst->inst_cache, ec);
+ CACHE_RETURN(&inst->inst_cache, &ec);
} else {
backentry_free(&ec);
}
+ ec_in_cache = 0; /* added to cache by id2entry - have to remove to try again */
slapi_pblock_set( pb, SLAPI_MODIFY_EXISTING_ENTRY, original_entry->ep_entry );
ec = original_entry;
if ( (original_entry = backentry_dup( e )) == NULL ) {
ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
}
- /* Put new entry 'ec' into the entry cache. */
- if (ec_in_cache && CACHE_ADD(&inst->inst_cache, ec, NULL) < 0) {
- LDAPDebug1Arg(LDAP_DEBUG_ANY,
- "ldbm_back_modify: adding %s to cache failed\n",
- slapi_entry_get_dn_const(ec->ep_entry));
- ldap_result_code = LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
LDAPDebug0Args(LDAP_DEBUG_BACKLDBM,
"Modify Retrying Transaction\n");
#ifndef LDBM_NO_BACKOFF_DELAY
@@ -603,7 +595,7 @@ ldbm_back_modify( Slapi_PBlock *pb )
}
if (retry_count == RETRY_TIMES) {
LDAPDebug( LDAP_DEBUG_ANY, "Retry count exceeded in modify\n", 0, 0, 0 );
- ldap_result_code= LDAP_OPERATIONS_ERROR;
+ ldap_result_code= LDAP_BUSY;
goto error_return;
}
@@ -629,6 +621,7 @@ ldbm_back_modify( Slapi_PBlock *pb )
ec->ep_entry->e_virtual_watermark = 0;
/* we must return both e (which has been deleted) and new entry ec */
+ /* cache_replace removes e from the caches */
cache_unlock_entry( &inst->inst_cache, e );
CACHE_RETURN( &inst->inst_cache, &e );
/*
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
index b3d8111..c7d821a 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
@@ -46,11 +46,11 @@
#include "back-ldbm.h"
static const char *moddn_get_newdn(Slapi_PBlock *pb, Slapi_DN *dn_olddn, Slapi_DN *dn_newrdn, Slapi_DN *dn_newsuperiordn);
-static void moddn_unlock_and_return_entries(backend *be,struct backentry **targetentry, struct backentry **existingentry);
+static void moddn_unlock_and_return_entry(backend *be,struct backentry **targetentry);
static int moddn_newrdn_mods(Slapi_PBlock *pb, const char *olddn, struct backentry *ec, Slapi_Mods *smods_wsi, int is_repl_op);
static IDList *moddn_get_children(back_txn *ptxn, Slapi_PBlock *pb, backend *be, struct backentry *parententry, Slapi_DN *parentdn, struct backentry ***child_entries, struct backdn ***child_dns);
static int moddn_rename_children(back_txn *ptxn, Slapi_PBlock *pb, backend *be, IDList *children, Slapi_DN *dn_parentdn, Slapi_DN *dn_newsuperiordn, struct backentry *child_entries[]);
-static int modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbminfo *li, struct backentry *e, struct backentry *ec, Slapi_Mods *smods1, Slapi_Mods *smods2, Slapi_Mods *smods3);
+static int modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbminfo *li, struct backentry *e, struct backentry **ec, Slapi_Mods *smods1, Slapi_Mods *smods2, Slapi_Mods *smods3, int *e_in_cache, int *ec_in_cache);
static void mods_remove_nsuniqueid(Slapi_Mods *smods);
#define MOD_SET_ERROR(rc, error, count) \
@@ -68,6 +68,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
struct backentry *e= NULL;
struct backentry *ec= NULL;
int ec_in_cache= 0;
+ int e_in_cache= 0;
back_txn txn;
back_txnid parent_txn;
int retval = -1;
@@ -81,7 +82,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
char *ldap_result_matcheddn= NULL;
struct backentry *parententry= NULL;
struct backentry *newparententry= NULL;
- struct backentry *existingentry= NULL;
struct backentry *original_entry = NULL;
struct backentry *original_parent = NULL;
struct backentry *original_newparent = NULL;
@@ -120,6 +120,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
const char *newdn = NULL;
char *newrdn = NULL;
int opreturn = 0;
+ int free_modrdn_existing_entry = 0;
/* sdn & parentsdn need to be initialized before "goto *_return" */
slapi_sdn_init(&dn_newdn);
@@ -254,6 +255,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
{
goto error_return;
}
+ free_modrdn_existing_entry = 1; /* need to free it */
}
/* <old superior> */
@@ -349,6 +351,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
ldap_result_code= -1;
goto error_return; /* error result sent by find_entry2modify() */
}
+ e_in_cache = 1; /* e is in the cache and locked */
/* Check that an entry with the same DN doesn't already exist. */
{
Slapi_Entry *entry;
@@ -518,17 +521,21 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
}
/* create it in the cache - prevents others from creating it */
- if (( cache_add_tentative( &inst->inst_cache, ec, NULL ) != 0 ) &&
+ if (( cache_add_tentative( &inst->inst_cache, ec, NULL ) != 0 ) ) {
+ ec_in_cache = 0; /* not in cache */
/* allow modrdn even if the src dn and dest dn are identical */
- ( 0 != slapi_sdn_compare((const Slapi_DN *)&dn_newdn,
- (const Slapi_DN *)sdn)) )
- {
- /* somebody must've created it between dn2entry() and here */
- /* JCMREPL - Hmm... we can't permit this to happen...? */
- ldap_result_code= LDAP_ALREADY_EXISTS;
- goto error_return;
+ if ( 0 != slapi_sdn_compare((const Slapi_DN *)&dn_newdn,
+ (const Slapi_DN *)sdn) ) {
+ /* somebody must've created it between dn2entry() and here */
+ /* JCMREPL - Hmm... we can't permit this to happen...? */
+ ldap_result_code= LDAP_ALREADY_EXISTS;
+ goto error_return;
+ }
+ /* so if the old dn is the same as the new dn, the entry will not be cached
+ until it is replaced with cache_replace */
+ } else {
+ ec_in_cache = 1;
}
- ec_in_cache= 1;
/* Build the list of modifications required to the existing entry */
{
@@ -725,15 +732,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
}
- if ( (original_parent = backentry_dup( parententry )) == NULL ) {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
- if ( newparententry &&
- ((original_newparent = backentry_dup( newparententry )) == NULL) ) {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
slapi_pblock_get(pb, SLAPI_MODRDN_TARGET_ENTRY, &target_entry);
if ( (original_targetentry = slapi_entry_dup(target_entry)) == NULL ) {
ldap_result_code= LDAP_OPERATIONS_ERROR;
@@ -754,6 +752,8 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
{
if (txn.back_txn_txn && (txn.back_txn_txn != parent_txn))
{
+ Slapi_Entry *ent = NULL;
+
dblayer_txn_abort(li,&txn);
/* txn is no longer valid - reset slapi_txn to the parent */
slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
@@ -761,6 +761,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn);
slapi_ch_free_string(&newrdn);
slapi_pblock_set(pb, SLAPI_MODRDN_NEWRDN, original_newrdn);
+ slapi_sdn_set_normdn_byref(&dn_newrdn, original_newrdn);
original_newrdn = slapi_ch_strdup(original_newrdn);
slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &dn_newsuperiordn);
@@ -769,27 +770,51 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
orig_dn_newsuperiordn = slapi_sdn_dup(orig_dn_newsuperiordn);
if (ec_in_cache) {
/* New entry 'ec' is in the entry cache.
- * Remove it from teh cache once. */
+ * Remove it from the cache . */
CACHE_REMOVE(&inst->inst_cache, ec);
- cache_unlock_entry(&inst->inst_cache, e);
- CACHE_RETURN(&inst->inst_cache, ec);
+ CACHE_RETURN(&inst->inst_cache, &ec);
+#ifdef DEBUG_CACHE
+ PR_ASSERT(ec == NULL);
+#endif
+ ec_in_cache = 0;
} else {
backentry_free(&ec);
}
- slapi_pblock_set( pb, SLAPI_MODRDN_EXISTING_ENTRY, original_entry->ep_entry );
+ /* make sure the original entry is back in the cache if it was removed */
+ if (!e_in_cache) {
+ CACHE_ADD(&inst->inst_cache, e, NULL);
+ e_in_cache = 1;
+ }
+ slapi_pblock_get( pb, SLAPI_MODRDN_EXISTING_ENTRY, &ent );
+ if (ent && (ent != original_entry->ep_entry)) {
+ slapi_entry_free(ent);
+ slapi_pblock_set( pb, SLAPI_MODRDN_EXISTING_ENTRY, NULL );
+ }
ec = original_entry;
if ( (original_entry = backentry_dup( ec )) == NULL ) {
ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
}
- if (ec_in_cache &&
+ slapi_pblock_set( pb, SLAPI_MODRDN_EXISTING_ENTRY, original_entry->ep_entry );
+ free_modrdn_existing_entry = 0; /* owned by original_entry now */
+ if (!ec_in_cache) {
/* Put the resetted entry 'ec' into the cache again. */
- (cache_add_tentative( &inst->inst_cache, ec, NULL ) != 0)) {
- LDAPDebug1Arg(LDAP_DEBUG_ANY,
- "ldbm_back_modrdn: adding %s to cache failed\n",
- slapi_entry_get_dn_const(ec->ep_entry));
- ldap_result_code = LDAP_OPERATIONS_ERROR;
- goto error_return;
+ if (cache_add_tentative( &inst->inst_cache, ec, NULL ) != 0) {
+ ec_in_cache = 0; /* not in cache */
+ /* allow modrdn even if the src dn and dest dn are identical */
+ if ( 0 != slapi_sdn_compare((const Slapi_DN *)&dn_newdn,
+ (const Slapi_DN *)sdn) ) {
+ LDAPDebug1Arg(LDAP_DEBUG_ANY,
+ "ldbm_back_modrdn: adding %s to cache failed\n",
+ slapi_entry_get_dn_const(ec->ep_entry));
+ ldap_result_code = LDAP_OPERATIONS_ERROR;
+ goto error_return;
+ }
+ /* so if the old dn is the same as the new dn, the entry will not be cached
+ until it is replaced with cache_replace */
+ } else {
+ ec_in_cache = 1;
+ }
}
slapi_pblock_get(pb, SLAPI_MODRDN_TARGET_ENTRY, &target_entry );
@@ -800,28 +825,16 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
goto error_return;
}
- backentry_free(&parententry);
- slapi_pblock_set( pb, SLAPI_MODRDN_PARENT_ENTRY, original_parent->ep_entry );
- parententry = original_parent;
- if ( (original_entry = backentry_dup( parententry )) == NULL ) {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
-
- backentry_free(&newparententry);
- if (original_newparent) {
- slapi_pblock_set( pb, SLAPI_MODRDN_NEWPARENT_ENTRY,
- original_newparent->ep_entry );
- }
- newparententry = original_entry;
- if ( newparententry &&
- ((original_entry = backentry_dup(newparententry)) == NULL) ) {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
/* We're re-trying */
LDAPDebug0Args(LDAP_DEBUG_BACKLDBM,
"Modrdn Retrying Transaction\n");
+#ifndef LDBM_NO_BACKOFF_DELAY
+ {
+ PRIntervalTime interval;
+ interval = PR_MillisecondsToInterval(slapi_rand() % 100);
+ DS_Sleep(interval);
+ }
+#endif
}
retval = dblayer_txn_begin(li,parent_txn,&txn);
if (0 != retval) {
@@ -852,7 +865,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
/*
* Update the indexes for the entry.
*/
- retval = modrdn_rename_entry_update_indexes(&txn, pb, li, e, ec, &smods_generated, &smods_generated_wsi, &smods_operation_wsi);
+ retval = modrdn_rename_entry_update_indexes(&txn, pb, li, e, &ec, &smods_generated, &smods_generated_wsi, &smods_operation_wsi, &e_in_cache, &ec_in_cache);
if (DB_LOCK_DEADLOCK == retval)
{
/* Retry txn */
@@ -979,11 +992,14 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
{
Slapi_RDN newsrdn;
slapi_rdn_init_sdn(&newsrdn, (const Slapi_DN *)&dn_newdn);
- rc = entryrdn_rename_subtree(be, (const Slapi_DN *)sdn, &newsrdn,
- (const Slapi_DN *)dn_newsuperiordn,
- e->ep_id, &txn);
+ retval = entryrdn_rename_subtree(be, (const Slapi_DN *)sdn, &newsrdn,
+ (const Slapi_DN *)dn_newsuperiordn,
+ e->ep_id, &txn);
slapi_rdn_done(&newsrdn);
- if (rc) {
+ if (retval != 0) {
+ if (retval == DB_LOCK_DEADLOCK) continue;
+ if (retval == DB_RUNRECOVERY || LDBM_OS_ERR_IS_DISKFULL(retval))
+ disk_full = 1;
MOD_SET_ERROR(ldap_result_code,
LDAP_OPERATIONS_ERROR, retry_count);
goto error_return;
@@ -1035,7 +1051,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
{
/* Failed */
LDAPDebug( LDAP_DEBUG_ANY, "Retry count exceeded in modrdn\n", 0, 0, 0 );
- ldap_result_code= LDAP_OPERATIONS_ERROR;
+ ldap_result_code= LDAP_BUSY;
goto error_return;
}
@@ -1128,12 +1144,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
}
retval= 0;
-#if 0 /* this new entry in the cache can be used for future; don't remove it */
- /* remove from cache so that memory can be freed by cache_return */
- if (ec_in_cache) {
- CACHE_REMOVE(&inst->inst_cache, ec);
- }
-#endif
goto common_return;
error_return:
@@ -1151,13 +1161,6 @@ error_return:
CACHE_REMOVE(&inst->inst_dncache, bdn);
CACHE_RETURN(&inst->inst_dncache, &bdn);
}
- if( ec!=NULL ) {
- if (ec_in_cache) {
- CACHE_REMOVE(&inst->inst_cache, ec);
- } else {
- backentry_free( &ec );
- }
- }
if(children)
{
int i = 0;
@@ -1245,13 +1248,6 @@ error_return:
common_return:
- /* Free up the resource we don't need any more */
- if(ec_in_cache) {
- CACHE_RETURN( &inst->inst_cache, &ec );
- }
-
- moddn_unlock_and_return_entries(be,&e,&existingentry);
-
/* result code could be used in the bepost plugin functions. */
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
/*
@@ -1259,6 +1255,32 @@ common_return:
*/
plugin_call_plugins (pb, SLAPI_PLUGIN_BE_POST_MODRDN_FN);
+ /* Free up the resource we don't need any more */
+ if (ec) {
+ /* remove the new entry from the cache if the op failed -
+ otherwise, leave it in */
+ if (ec_in_cache && retval) {
+ CACHE_REMOVE( &inst->inst_cache, ec );
+ }
+ if (ec_in_cache) {
+ CACHE_RETURN( &inst->inst_cache, &ec );
+ } else {
+ backentry_free( &ec );
+ }
+ ec = NULL;
+ ec_in_cache = 0;
+ }
+
+ /* put e back in the cache if the modrdn failed */
+ if (e) {
+ if (!e_in_cache && retval) {
+ CACHE_ADD(&inst->inst_cache, e, NULL);
+ e_in_cache = 1;
+ }
+ }
+
+ moddn_unlock_and_return_entry(be,&e);
+
if (ruv_c_init) {
modify_term(&ruv_c, be);
}
@@ -1281,7 +1303,11 @@ common_return:
slapi_sdn_done(&dn_parentdn);
modify_term(&parent_modify_context,be);
modify_term(&newparent_modify_context,be);
- done_with_pblock_entry(pb,SLAPI_MODRDN_EXISTING_ENTRY);
+ if (free_modrdn_existing_entry) {
+ done_with_pblock_entry(pb,SLAPI_MODRDN_EXISTING_ENTRY);
+ } else { /* owned by original_entry */
+ slapi_pblock_set(pb, SLAPI_MODRDN_EXISTING_ENTRY, NULL);
+ }
done_with_pblock_entry(pb,SLAPI_MODRDN_PARENT_ENTRY);
done_with_pblock_entry(pb,SLAPI_MODRDN_NEWPARENT_ENTRY);
done_with_pblock_entry(pb,SLAPI_MODRDN_TARGET_ENTRY);
@@ -1354,10 +1380,9 @@ moddn_get_newdn(Slapi_PBlock *pb, Slapi_DN *dn_olddn, Slapi_DN *dn_newrdn, Slapi
* Return the entries to the cache.
*/
static void
-moddn_unlock_and_return_entries(
+moddn_unlock_and_return_entry(
backend *be,
- struct backentry **targetentry,
- struct backentry **existingentry)
+ struct backentry **targetentry)
{
ldbm_instance *inst = (ldbm_instance *) be->be_instance_info;
@@ -1367,10 +1392,6 @@ moddn_unlock_and_return_entries(
CACHE_RETURN( &inst->inst_cache, targetentry );
*targetentry= NULL;
}
- if ( *existingentry!=NULL ) {
- CACHE_RETURN( &inst->inst_cache, existingentry );
- *existingentry= NULL;
- }
}
@@ -1540,8 +1561,8 @@ moddn_newrdn_mods(Slapi_PBlock *pb, const char *olddn, struct backentry *ec, Sla
}
else
{
- LDAPDebug( LDAP_DEBUG_TRACE, "moddn_newrdn_mods failed: could not parse new rdn %s\n",
- newrdn, 0, 0);
+ LDAPDebug( LDAP_DEBUG_TRACE, "moddn_newrdn_mods failed: could not parse new rdn %s\n",
+ newrdn, 0, 0);
return LDAP_OPERATIONS_ERROR;
}
@@ -1568,7 +1589,7 @@ mods_remove_nsuniqueid(Slapi_Mods *smods)
* mods contains the list of attribute change made.
*/
static int
-modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbminfo *li, struct backentry *e, struct backentry *ec, Slapi_Mods *smods1, Slapi_Mods *smods2, Slapi_Mods *smods3)
+modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbminfo *li, struct backentry *e, struct backentry **ec, Slapi_Mods *smods1, Slapi_Mods *smods2, Slapi_Mods *smods3, int *e_in_cache, int *ec_in_cache)
{
backend *be;
ldbm_instance *inst;
@@ -1576,36 +1597,41 @@ modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbm
char *msg;
Slapi_Operation *operation;
int is_ruv = 0; /* True if the current entry is RUV */
+ int orig_ec_in_cache = 0;
slapi_pblock_get( pb, SLAPI_BACKEND, &be );
slapi_pblock_get( pb, SLAPI_OPERATION, &operation );
is_ruv = operation_is_flag_set(operation, OP_FLAG_REPL_RUV);
inst = (ldbm_instance *) be->be_instance_info;
+ orig_ec_in_cache = *ec_in_cache;
/*
* Update the ID to Entry index.
* Note that id2entry_add replaces the entry, so the Entry ID stays the same.
*/
- retval = id2entry_add( be, ec, ptxn );
+ retval = id2entry_add( be, *ec, ptxn );
if (DB_LOCK_DEADLOCK == retval)
{
/* Retry txn */
+ LDAPDebug0Args( LDAP_DEBUG_BACKLDBM, "modrdn_rename_entry_update_indexes: id2entry_add deadlock\n" );
goto error_return;
}
if (retval != 0)
{
- LDAPDebug( LDAP_DEBUG_ANY, "id2entry_add failed, err=%d %s\n", retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
+ LDAPDebug( LDAP_DEBUG_ANY, "modrdn_rename_entry_update_indexes: id2entry_add failed, err=%d %s\n", retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
goto error_return;
}
+ *ec_in_cache = 1; /* id2entry_add adds to cache if not already in */
if(smods1!=NULL && slapi_mods_get_num_mods(smods1)>0)
{
/*
* update the indexes: lastmod, rdn, etc.
*/
- retval = index_add_mods( be, slapi_mods_get_ldapmods_byref(smods1), e, ec, ptxn );
+ retval = index_add_mods( be, slapi_mods_get_ldapmods_byref(smods1), e, *ec, ptxn );
if (DB_LOCK_DEADLOCK == retval)
{
/* Retry txn */
+ LDAPDebug0Args( LDAP_DEBUG_BACKLDBM, "modrdn_rename_entry_update_indexes: index_add_mods1 deadlock\n" );
goto error_return;
}
if (retval != 0)
@@ -1625,10 +1651,11 @@ modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbm
/*
* update the indexes: lastmod, rdn, etc.
*/
- retval = index_add_mods( be, slapi_mods_get_ldapmods_byref(smods2), e, ec, ptxn );
+ retval = index_add_mods( be, slapi_mods_get_ldapmods_byref(smods2), e, *ec, ptxn );
if (DB_LOCK_DEADLOCK == retval)
{
/* Retry txn */
+ LDAPDebug0Args( LDAP_DEBUG_BACKLDBM, "modrdn_rename_entry_update_indexes: index_add_mods2 deadlock\n" );
goto error_return;
}
if (retval != 0)
@@ -1642,10 +1669,11 @@ modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbm
/*
* update the indexes: lastmod, rdn, etc.
*/
- retval = index_add_mods( be, slapi_mods_get_ldapmods_byref(smods3), e, ec, ptxn );
+ retval = index_add_mods( be, slapi_mods_get_ldapmods_byref(smods3), e, *ec, ptxn );
if (DB_LOCK_DEADLOCK == retval)
{
/* Retry txn */
+ LDAPDebug0Args( LDAP_DEBUG_BACKLDBM, "modrdn_rename_entry_update_indexes: index_add_mods3 deadlock\n" );
goto error_return;
}
if (retval != 0)
@@ -1661,10 +1689,11 @@ modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbm
*/
if (!is_ruv)
{
- retval= vlv_update_all_indexes(ptxn, be, pb, e, ec);
+ retval= vlv_update_all_indexes(ptxn, be, pb, e, *ec);
if (DB_LOCK_DEADLOCK == retval)
{
/* Abort and re-try */
+ LDAPDebug0Args( LDAP_DEBUG_BACKLDBM, "modrdn_rename_entry_update_indexes: vlv_update_all_indexes deadlock\n" );
goto error_return;
}
if (retval != 0)
@@ -1673,9 +1702,18 @@ modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbm
goto error_return;
}
}
- if (cache_replace( &inst->inst_cache, e, ec ) != 0 ) {
+ if (cache_replace( &inst->inst_cache, e, *ec ) != 0 ) {
+ LDAPDebug0Args( LDAP_DEBUG_BACKLDBM, "modrdn_rename_entry_update_indexes cache_replace failed\n");
retval= -1;
goto error_return;
+ } else {
+ *e_in_cache = 0; /* e un-cached */
+ }
+ if (orig_ec_in_cache) {
+ /* ec was already added to the cache via cache_add_tentative (to reserve its spot in the cache)
+ and/or id2entry_add - so it already had one refcount - cache_replace adds another refcount -
+ drop the extra ref added by cache_replace */
+ CACHE_RETURN( &inst->inst_cache, ec );
}
error_return:
return retval;
@@ -1687,7 +1725,7 @@ moddn_rename_child_entry(
Slapi_PBlock *pb,
struct ldbminfo *li,
struct backentry *e,
- struct backentry *ec,
+ struct backentry **ec,
int parentdncomps,
char **newsuperiordns,
int newsuperiordncomps,
@@ -1711,8 +1749,10 @@ moddn_rename_child_entry(
int olddncomps= 0;
int need= 1; /* For the '\0' */
int i;
+ int e_in_cache = 1;
+ int ec_in_cache = 0;
- olddn = slapi_entry_get_dn(ec->ep_entry);
+ olddn = slapi_entry_get_dn((*ec)->ep_entry);
if (NULL == olddn) {
return retval;
}
@@ -1747,9 +1787,9 @@ moddn_rename_child_entry(
}
}
slapi_ldap_value_free( olddns );
- slapi_entry_set_dn( ec->ep_entry, newdn );
+ slapi_entry_set_dn( (*ec)->ep_entry, newdn );
/* add the entrydn operational attributes */
- add_update_entrydn_operational_attributes (ec);
+ add_update_entrydn_operational_attributes (*ec);
/*
* Update the DN CSN of the entry.
@@ -1767,13 +1807,14 @@ moddn_rename_child_entry(
slapi_mods_add( &smods, LDAP_MOD_DELETE, LDBM_ENTRYDN_STR,
strlen( backentry_get_ndn(e) ), backentry_get_ndn(e) );
slapi_mods_add( &smods, LDAP_MOD_REPLACE, LDBM_ENTRYDN_STR,
- strlen( backentry_get_ndn(ec) ), backentry_get_ndn(ec) );
+ strlen( backentry_get_ndn(*ec) ), backentry_get_ndn(*ec) );
smodsp = &smods;
/*
* Update all the indexes.
*/
retval = modrdn_rename_entry_update_indexes(ptxn, pb, li, e, ec,
- smodsp, NULL, NULL);
+ smodsp, NULL, NULL,
+ &e_in_cache, &ec_in_cache);
/* JCMREPL - Should the children get updated modifiersname and lastmodifiedtime? */
slapi_mods_done(&smods);
}
@@ -1850,7 +1891,7 @@ moddn_rename_children(
opcsn = operation_get_csn (operation);
for (i=0,retval=0; retval == 0 && child_entries[i] && child_entry_copies[i]; i++) {
retval = moddn_rename_child_entry(ptxn, pb, li, child_entries[i],
- child_entry_copies[i], parentdncomps,
+ &child_entry_copies[i], parentdncomps,
newsuperiordns, newsuperiordncomps,
opcsn );
}
diff --git a/ldap/servers/slapd/back-ldbm/misc.c b/ldap/servers/slapd/back-ldbm/misc.c
index 8140818..a56069b 100644
--- a/ldap/servers/slapd/back-ldbm/misc.c
+++ b/ldap/servers/slapd/back-ldbm/misc.c
@@ -53,7 +53,7 @@ void ldbm_nasty(const char* str, int c, int err)
char buffer[200];
if (err == DB_LOCK_DEADLOCK) {
PR_snprintf(buffer,200,"%s WARNING %d",str,c);
- LDAPDebug(LDAP_DEBUG_TRACE,"%s, err=%d %s\n",
+ LDAPDebug(LDAP_DEBUG_BACKLDBM,"%s, err=%d %s\n",
buffer,err,(msg = dblayer_strerror( err )) ? msg : "");
} else if (err == DB_RUNRECOVERY) {
LDAPDebug2Args(LDAP_DEBUG_ANY, "FATAL ERROR at %s (%d); "
diff --git a/ldap/servers/slapd/back-ldbm/seq.c b/ldap/servers/slapd/back-ldbm/seq.c
index ac958ad..1435ba2 100644
--- a/ldap/servers/slapd/back-ldbm/seq.c
+++ b/ldap/servers/slapd/back-ldbm/seq.c
@@ -240,6 +240,9 @@ ldbm_back_seq( Slapi_PBlock *pb )
idl = idl_fetch( be, db, &key, NULL, 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;
} else {
break;
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 22237ce..3138ed3 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1242,7 +1242,8 @@ enum
BE_STATE_STOPPED = 1, /* backend is initialized but not started */
BE_STATE_STARTED, /* backend is started */
BE_STATE_CLEANED, /* backend was cleaned up */
- BE_STATE_DELETED /* backend is removed */
+ BE_STATE_DELETED, /* backend is removed */
+ BE_STATE_STOPPING /* told to stop but not yet stopped */
};
struct conn;
11 years, 6 months
Branch '389-ds-base-1.2.11' - 3 commits - ldap/servers
by Richard Allen Megginson
ldap/servers/plugins/replication/repl5_plugins.c | 5
ldap/servers/plugins/usn/usn.c | 47 --
ldap/servers/plugins/usn/usn_cleanup.c | 3
ldap/servers/slapd/add.c | 7
ldap/servers/slapd/back-ldbm/cache.c | 53 +-
ldap/servers/slapd/back-ldbm/dblayer.c | 420 ++++++++++++++++++++
ldap/servers/slapd/back-ldbm/index.c | 62 ++
ldap/servers/slapd/back-ldbm/ldbm_add.c | 2
ldap/servers/slapd/back-ldbm/ldbm_delete.c | 152 ++++---
ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c | 476 +++++++++++++++++------
ldap/servers/slapd/back-ldbm/ldbm_modify.c | 15
ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 245 ++++++-----
ldap/servers/slapd/back-ldbm/misc.c | 2
ldap/servers/slapd/back-ldbm/seq.c | 3
ldap/servers/slapd/slap.h | 3
15 files changed, 1122 insertions(+), 373 deletions(-)
New commits:
commit 73e077189820130c93e25e359d5935794dbbf3ee
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Wed May 23 19:23:24 2012 -0600
Ticket #383 - usn + mmr = deletions are not replicated
https://fedorahosted.org/389/ticket/383
Resolves: Ticket #383
Bug Description: usn + mmr = deletions are not replicated
Reviewed by: mreynolds (Thanks!)
Branch: master
Fix Description: The problem was that because usn was creating a tombstone,
it was also setting the OP_FLAG_TOMBSTONE flag in the operation, which was
causing the operation to think it was deleting a tombstone. The fix is to
not set this flag, and instead have operations that delete tombstones to
set that flag explicitly when creating the delete op request.
In addition, the CSN for delete ops was not being logged - the usn bepostop
was deleting it, even when replication was being used. Previously the csn
was needed as a "trigger" to tell the ldbm_back_delete code to create a
tombstone rather than deleting the entry outright. Instead, use the
slapi_operation_get_replica_attr (pb, operation,
"nsds5ReplicaTombstonePurgeInterval,
&create_tombstone_entry)
to determine whether or not to create a tombstone entry. Both replication
and usn configure this, so if using one or both of those, tombstones will
be created, otherwise, not.
Platforms tested: RHEL6 x86_64, Fedora 17
Flag Day: no
Doc impact: no
diff --git a/ldap/servers/plugins/usn/usn.c b/ldap/servers/plugins/usn/usn.c
index 812d83d..0273fd1 100644
--- a/ldap/servers/plugins/usn/usn.c
+++ b/ldap/servers/plugins/usn/usn.c
@@ -45,8 +45,6 @@ static Slapi_PluginDesc pdesc = {
"USN", VENDOR, DS_PACKAGE_VERSION,
"USN (Update Sequence Number) plugin" };
-static CSNGen *_usn_csngen = NULL;
-
static void *_usn_identity = NULL;
static int usn_preop_init(Slapi_PBlock *pb);
@@ -152,13 +150,6 @@ usn_preop_init(Slapi_PBlock *pb)
{
int rc = 0;
int predel = SLAPI_PLUGIN_PRE_DELETE_FN;
- /* set up csn generator for tombstone */
- _usn_csngen = csngen_new(USN_CSNGEN_ID, NULL);
- if (NULL == _usn_csngen) {
- slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
- "usn_preop_init: csngen_new failed\n");
- rc = -1;
- }
if (slapi_pblock_set(pb, predel, (void *)usn_preop_delete) != 0) {
slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
@@ -302,15 +293,11 @@ bail:
return rc;
}
-/*
- * usn_close: release the csn generator used to convert an entry to tombstone
- */
static int
usn_close(Slapi_PBlock *pb)
{
slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM, "--> usn_close\n");
- csngen_free(&_usn_csngen);
g_plugin_started = 0;
slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM, "<-- usn_close\n");
@@ -325,32 +312,14 @@ static int
usn_preop_delete(Slapi_PBlock *pb)
{
int rc = 0;
- CSN *csn = NULL;
- CSN *orig_csn = NULL;
Slapi_Operation *op = NULL;
slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
"--> usn_preop_delete\n");
slapi_pblock_get(pb, SLAPI_OPERATION, &op);
- orig_csn = operation_get_csn(op);
-
- if (NULL == orig_csn) {
- /*
- * No other plugins hasn't set csn yet, so let's set USN's csn.
- * If other plugin overrides csn and replica_attr_handler, that's fine.
- */
- rc = csngen_new_csn(_usn_csngen, &csn, PR_FALSE /* notify */);
- if (CSN_SUCCESS != rc) {
- slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
- "usn_preop_delete: csngen_new failed (%d)\n", rc);
- csn_free(&csn);
- goto bail;
- }
- operation_set_csn(op, csn);
- slapi_operation_set_replica_attr_handler(op, (void *)usn_get_attr);
- }
-bail:
+ slapi_operation_set_replica_attr_handler(op, (void *)usn_get_attr);
+
slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
"<-- usn_preop_delete\n");
@@ -486,11 +455,6 @@ usn_betxnpreop_delete(Slapi_PBlock *pb)
rc = LDAP_PARAM_ERROR;
goto bail;
}
- if (e->e_flags & SLAPI_ENTRY_FLAG_TOMBSTONE) {
- Slapi_Operation *op = NULL;
- slapi_pblock_get(pb, SLAPI_OPERATION, &op);
- slapi_operation_set_flag(op, OP_FLAG_TOMBSTONE_ENTRY);
- }
_usn_add_next_usn(e, be);
bail:
slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
@@ -615,17 +579,10 @@ usn_bepostop_delete (Slapi_PBlock *pb)
{
int rc = -1;
Slapi_Backend *be = NULL;
- Slapi_Operation *op = NULL;
- CSN *csn = NULL;
slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
"--> usn_bepostop\n");
- slapi_pblock_get(pb, SLAPI_OPERATION, &op);
- csn = operation_get_csn(op);
- csn_free(&csn);
- operation_set_csn(op, NULL);
-
/* if op is not successful, don't increment the counter */
slapi_pblock_get(pb, SLAPI_RESULT_CODE, &rc);
if (LDAP_SUCCESS != rc) {
diff --git a/ldap/servers/plugins/usn/usn_cleanup.c b/ldap/servers/plugins/usn/usn_cleanup.c
index 20decae..6f9410e 100644
--- a/ldap/servers/plugins/usn/usn_cleanup.c
+++ b/ldap/servers/plugins/usn/usn_cleanup.c
@@ -145,6 +145,7 @@ usn_cleanup_thread(void *arg)
for (ep = entries; ep && *ep; ep++) {
int delrv = 0;
const Slapi_DN *sdn = slapi_entry_get_sdn_const(*ep);
+ int opflags = OP_FLAG_TOMBSTONE_ENTRY;
/* check for shutdown */
if(g_get_shutdown()){
@@ -156,7 +157,7 @@ usn_cleanup_thread(void *arg)
}
slapi_delete_internal_set_pb(delete_pb, slapi_sdn_get_dn(sdn),
- NULL, NULL, usn_get_identity(), 0);
+ NULL, NULL, usn_get_identity(), opflags);
slapi_delete_internal_pb(delete_pb);
slapi_pblock_get(delete_pb, SLAPI_PLUGIN_INTOP_RESULT, &delrv);
if (LDAP_SUCCESS != delrv) {
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
index 846d87b..0427b45 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
@@ -267,12 +267,8 @@ ldbm_back_delete( Slapi_PBlock *pb )
opcsn = operation_get_csn (operation);
if (!delete_tombstone_entry)
{
- /* If both USN and replication is enabled, csn set by replication
- * should be honored. */
- if ((opcsn == NULL || ldbm_usn_enabled(be)) &&
- !is_fixup_operation && operation->o_csngen_handler)
+ if ((opcsn == NULL) && !is_fixup_operation && operation->o_csngen_handler)
{
- csn_free(&opcsn); /* free opcsn set by USN plugin, if any */
/*
* Current op is a user request. Opcsn will be assigned
* by entry_assign_operation_csn() if the dn is in an
@@ -286,14 +282,15 @@ ldbm_back_delete( Slapi_PBlock *pb )
{
entry_set_maxcsn (e->ep_entry, opcsn);
}
- /*
- * We are dealing with replication and if we haven't been called to
- * remove a tombstone, then it's because we want to create a new one.
- */
- if ( slapi_operation_get_replica_attr (pb, operation, "nsds5ReplicaTombstonePurgeInterval", &create_tombstone_entry) == 0)
- {
- create_tombstone_entry = (create_tombstone_entry < 0) ? 0 : 1;
- }
+ }
+ /*
+ * We are dealing with replication and if we haven't been called to
+ * remove a tombstone, then it's because we want to create a new one.
+ */
+ if ( slapi_operation_get_replica_attr (pb, operation, "nsds5ReplicaTombstonePurgeInterval",
+ &create_tombstone_entry) == 0 )
+ {
+ create_tombstone_entry = (create_tombstone_entry < 0) ? 0 : 1;
}
}
commit 7146bb325de67b036dfa39b898c030ee414337f9
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Wed May 23 09:46:30 2012 -0600
Ticket #382 - DS Shuts down intermittently
https://fedorahosted.org/389/ticket/382
Resolves: Ticket #382
Bug Description: DS Shuts down intermittently
Reviewed by: nhosoi (Thanks!)
Branch: 389-ds-base-1.2.11
Fix Description: ldbm_back_delete should not touch the backentry to
be deleted while it is in the cache. Any mods made by any plugins should
be made to the tombstone or to a copy of the original entry.
Platforms tested: Fedora 17
Flag Day: no
Doc impact: no
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
index 237085c..846d87b 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
@@ -60,7 +60,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
struct ldbminfo *li = NULL;
struct backentry *e = NULL;
struct backentry *tombstone = NULL;
- Slapi_Entry *original_entry = NULL;
struct backentry *original_tombstone = NULL;
char *dn = NULL;
back_txn txn;
@@ -80,7 +79,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
Slapi_DN sdn;
Slapi_DN *sdnp = NULL;
char *e_uniqueid = NULL;
- Slapi_DN *nscpEntrySDN = NULL;
+ Slapi_DN nscpEntrySDN;
int dblock_acquired= 0;
Slapi_Operation *operation;
CSN *opcsn = NULL;
@@ -110,6 +109,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
/* sdn needs to be initialized before "goto *_return */
slapi_sdn_init(&sdn);
+ slapi_sdn_init(&nscpEntrySDN);
/* dblayer_txn_init needs to be called before "goto error_return" */
dblayer_txn_init(li,&txn);
@@ -388,7 +388,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
childuniqueid);
Slapi_Value *tomb_value;
- nscpEntrySDN = slapi_entry_get_sdn(e->ep_entry);
+ slapi_sdn_set_ndn_byval(&nscpEntrySDN, slapi_sdn_get_ndn(slapi_entry_get_sdn(e->ep_entry)));
/* Copy the entry unique_id for URP conflict checking */
e_uniqueid = slapi_ch_strdup(childuniqueid);
@@ -418,10 +418,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
/* The suffix entry has no parent */
slapi_entry_add_string(tombstone->ep_entry, SLAPI_ATTR_VALUE_PARENT_UNIQUEID, parentuniqueid);
}
- if(nscpEntrySDN!=NULL)
- {
- slapi_entry_add_string(tombstone->ep_entry, SLAPI_ATTR_NSCP_ENTRYDN, slapi_sdn_get_ndn(nscpEntrySDN));
- }
+ slapi_entry_add_string(tombstone->ep_entry, SLAPI_ATTR_NSCP_ENTRYDN, slapi_sdn_get_ndn(&nscpEntrySDN));
tomb_value = slapi_value_new_string(SLAPI_ATTR_VALUE_TOMBSTONE);
value_update_csn(tomb_value, CSN_TYPE_VALUE_UPDATED,
operation_get_csn(operation));
@@ -449,11 +446,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
}
}
- if ( (original_entry = slapi_entry_dup( e->ep_entry )) == NULL ) {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
-
/*
* So, we believe that no code up till here actually added anything
* to the persistent store. From now on, we're transacted
@@ -469,20 +461,14 @@ ldbm_back_delete( Slapi_PBlock *pb )
/* reset original entry */
slapi_pblock_get( pb, SLAPI_DELETE_EXISTING_ENTRY, &ent );
- if (ent && (ent != original_entry) && free_delete_existing_entry) {
+ if (ent && free_delete_existing_entry) {
slapi_entry_free(ent);
slapi_pblock_set( pb, SLAPI_DELETE_EXISTING_ENTRY, NULL );
}
- slapi_entry_free(e->ep_entry);
- e->ep_entry = original_entry;
- if ( (original_entry = slapi_entry_dup( e->ep_entry )) == NULL ) {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
- slapi_pblock_set( pb, SLAPI_DELETE_EXISTING_ENTRY, original_entry );
- free_delete_existing_entry = 0; /* owned by original_entry now */
- if (nscpEntrySDN) {
- nscpEntrySDN = slapi_entry_get_sdn(original_entry);
+ slapi_pblock_set( pb, SLAPI_DELETE_EXISTING_ENTRY, slapi_entry_dup( e->ep_entry ) );
+ free_delete_existing_entry = 1; /* must free the dup */
+ if (create_tombstone_entry) {
+ slapi_sdn_set_ndn_byval(&nscpEntrySDN, slapi_sdn_get_ndn(slapi_entry_get_sdn(e->ep_entry)));
}
/* reset tombstone entry */
@@ -524,8 +510,10 @@ ldbm_back_delete( Slapi_PBlock *pb )
/* call the transaction pre delete plugins just after creating
* the transaction */
- slapi_pblock_get( pb, SLAPI_DELETE_BEPREOP_ENTRY, &orig_entry );
- slapi_pblock_set( pb, SLAPI_DELETE_BEPREOP_ENTRY, e->ep_entry );
+ /* these should not need to modify the entry to be deleted -
+ if for some reason they ever do, do not use e->ep_entry since
+ it could be in the cache and referenced by other search threads -
+ instead, have them modify a copy of the entry */
retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN);
if (retval) {
LDAPDebug1Arg( LDAP_DEBUG_TRACE,
@@ -544,13 +532,12 @@ ldbm_back_delete( Slapi_PBlock *pb )
}
goto error_return;
}
- slapi_pblock_set( pb, SLAPI_DELETE_BEPREOP_ENTRY, orig_entry );
- orig_entry = NULL;
if(create_tombstone_entry)
{
-
slapi_pblock_get( pb, SLAPI_DELETE_BEPREOP_ENTRY, &orig_entry );
+ /* this is ok because no other threads should be accessing
+ the tombstone entry */
slapi_pblock_set( pb, SLAPI_DELETE_BEPREOP_ENTRY,
tombstone->ep_entry );
rc = plugin_call_plugins(pb,
@@ -696,7 +683,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
goto error_return;
}
retval = index_addordel_string(be, SLAPI_ATTR_NSCP_ENTRYDN,
- slapi_sdn_get_ndn(nscpEntrySDN),
+ slapi_sdn_get_ndn(&nscpEntrySDN),
tombstone->ep_id, BE_INDEX_ADD, &txn);
if (DB_LOCK_DEADLOCK == retval) {
LDAPDebug( LDAP_DEBUG_ARGS,
@@ -1183,13 +1170,13 @@ diskfull_return:
}
if (free_delete_existing_entry) {
done_with_pblock_entry(pb, SLAPI_DELETE_EXISTING_ENTRY);
- } else { /* owned by original_entry */
+ } else { /* owned by someone else */
slapi_pblock_set(pb, SLAPI_DELETE_EXISTING_ENTRY, NULL);
}
- slapi_entry_free(original_entry);
backentry_free(&original_tombstone);
slapi_ch_free((void**)&errbuf);
slapi_sdn_done(&sdn);
+ slapi_sdn_done(&nscpEntrySDN);
slapi_ch_free_string(&e_uniqueid);
if (pb->pb_conn)
{
commit 48b8ace54583662306c75f22f2f243fc274251af
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Mon May 14 15:14:28 2012 -0600
Ticket #360 - ldapmodify returns Operations error
https://fedorahosted.org/389/ticket/360
Resolves: Ticket #360
Bug Description: ldapmodify returns Operations error
Reviewed by: mreynolds (Thanks!)
Branch: master
Fix Description:
1) Fix handling of DB_LOCK_DEADLOCK conditions. When a database operation
returns DB_LOCK_DEADLOCK, all cursors must be closed, and the transaction
aborted and retried. If not in a transaction, the operation may be retried
immediately. This fix adds this logic to many places in the db code where
it was lacking.
2) Fix resetting of the data when an operation has to be retried. When
a transaction has to be retried, we must reset the data to the same state
it was before any of the operations in the transaction were attempted. This
includes the entry cache state, which was lacking in a number of ways. One
major problem with resetting the cache is that cache_add_tentative adds an
entry to the dncache, but not the idcache, in order to reserve a space in
the cache, and to prevent other entries with the same DN from being added
while the operation is in progress. There was no good way to remove this
entry. In the case of modrdn, removing the tentative entry would also
remove the real entry since they share the same entryid. This fix also
makes sure that in error conditions, temporary entries are removed from
the cache and properly freed, and real entries are "rolled back" into the
cache.
3) Added a transaction stress thread. This thread can simulate various types
of read and write locking that can cause conflicts and trigger regular
database operations to return DB_LOCK_DEADLOCK. The usual culprit is read
locks which are held on pages that are searched outside of a transaction.
The stress thread can lock, via read cursors, all of the pages in all of
the indexes in the database, and hold these pages for some set period of
time, then loop and do it again.
4) It is quite easy to get the database in a deadlock situation, where a
update operation is waiting for a read lock to be released in order to
write to a page, while a search operation is waiting for a write lock to
be released in order to read lock the page. If we are going to allow
concurrent searches during update operations, without making search requests
transacted, we need to have some way to detect these deadlocks. The fastest
way to do it is to use the DB_TXN_NOWAIT flag when starting transactions.
This tells bdb to return immediately with a DB_LOCK_DEADLOCK if the
transaction cannot proceed due to a locked page (e.g. a search request
has read locked a page). Alternately, we could have transactions wait
for some specified period of time, but if we think that this type of thread
contention is going to be rare, it makes sense to return immediately, if
our deadlock handling is fast and robust.
5) Fixed some memory leaks
6) The txn_test thread needs to know when the backend databases are
available - had to add a backend flag BE_STATE_STOPPING so that
the txn_thread knows when the databases are available
7) If the op was retried RETRY_TIMES times, return LDAP_BUSY instead of
OPERATIONS_ERROR - the problem really is that the server is busy with
other transactions, and the operation could go through if the client
were to retry.
8) Renaming an entry without changing the dn e.g. changing the case does
not cache the entry, so handle that
9) Added a delay when a deadlock is encountered in modrdn - same as the
other add/mod/del cases
Platforms tested: RHEL6 x86_64, Fedora 17
Flag Day: yes
Doc impact: yes
diff --git a/ldap/servers/plugins/replication/repl5_plugins.c b/ldap/servers/plugins/replication/repl5_plugins.c
index dfbb80e..5ca6d90 100644
--- a/ldap/servers/plugins/replication/repl5_plugins.c
+++ b/ldap/servers/plugins/replication/repl5_plugins.c
@@ -997,6 +997,11 @@ write_changelog_and_ruv (Slapi_PBlock *pb)
return 0;
}
+ slapi_pblock_get(pb, SLAPI_RESULT_CODE, &rc);
+ if (rc) { /* op failed - just return */
+ return 0;
+ }
+
/* we only log changes for operations applied to a replica */
repl_obj = replica_get_replica_for_op (pb);
if (repl_obj == NULL)
diff --git a/ldap/servers/slapd/add.c b/ldap/servers/slapd/add.c
index 9966a27..55deeee 100644
--- a/ldap/servers/slapd/add.c
+++ b/ldap/servers/slapd/add.c
@@ -665,6 +665,7 @@ static void op_shared_add (Slapi_PBlock *pb)
int rc;
Slapi_Entry *ec;
Slapi_DN *add_target_sdn = NULL;
+ Slapi_Entry *save_e = NULL;
slapi_pblock_set(pb, SLAPI_PLUGIN, be->be_database);
set_db_default_result_handlers(pb);
@@ -678,6 +679,8 @@ static void op_shared_add (Slapi_PBlock *pb)
if (be->be_add != NULL)
{
rc = (*be->be_add)(pb);
+ /* backend may change this if errors and not consumed */
+ slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &save_e);
slapi_pblock_set(pb, SLAPI_ADD_ENTRY, ec);
if (rc == 0)
{
@@ -703,6 +706,10 @@ static void op_shared_add (Slapi_PBlock *pb)
}
else
{
+ /* restore e so we can free it below */
+ if (save_e) {
+ e = save_e;
+ }
if (rc == SLAPI_FAIL_DISKFULL)
{
operation_out_of_disk_space();
diff --git a/ldap/servers/slapd/back-ldbm/cache.c b/ldap/servers/slapd/back-ldbm/cache.c
index 2ef0f28..045b1eb 100644
--- a/ldap/servers/slapd/back-ldbm/cache.c
+++ b/ldap/servers/slapd/back-ldbm/cache.c
@@ -294,7 +294,7 @@ dump_hash(Hashtable *ht)
continue;
}
do {
- PR_snprintf(ep_id, 16, "%u", ((struct backcommon *)e)->ep_id);
+ PR_snprintf(ep_id, 16, "%u-%u", ((struct backcommon *)e)->ep_id, ((struct backcommon *)e)->ep_refcnt);
len = strlen(ep_id);
if (ids_size < len + 1) {
LDAPDebug1Arg(LDAP_DEBUG_ANY, "%s\n", ep_ids);
@@ -857,7 +857,7 @@ entrycache_remove_int(struct cache *cache, struct backentry *e)
const char *uuid;
#endif
- LOG("=> entrycache_remove_int (%s)\n", backentry_get_ndn(e), 0, 0);
+ LOG("=> entrycache_remove_int (%s) (%u) (%u)\n", backentry_get_ndn(e), e->ep_id, e->ep_refcnt);
if (e->ep_state & ENTRY_STATE_NOTINCACHE)
{
return ret;
@@ -876,13 +876,22 @@ entrycache_remove_int(struct cache *cache, struct backentry *e)
{
LOG("remove %s from dn hash failed\n", ndn, 0, 0);
}
- if (remove_hash(cache->c_idtable, &(e->ep_id), sizeof(ID)))
+ /* if entry was added tentatively, it will be in the dntable
+ but not in the idtable - we cannot just remove it from
+ the idtable - in the case of modrdn, this will remove
+ the _real_ entry from the idtable, leading to a cache
+ imbalance
+ */
+ if (!(e->ep_state & ENTRY_STATE_CREATING))
{
- ret = 0;
- }
- else
- {
- LOG("remove %d from id hash failed\n", e->ep_id, 0, 0);
+ if (remove_hash(cache->c_idtable, &(e->ep_id), sizeof(ID)))
+ {
+ ret = 0;
+ }
+ else
+ {
+ LOG("remove %d from id hash failed\n", e->ep_id, 0, 0);
+ }
}
#ifdef UUIDCACHE_ON
uuid = slapi_entry_get_uniqueid(e->ep_entry);
@@ -907,6 +916,11 @@ entrycache_remove_int(struct cache *cache, struct backentry *e)
/* mark for deletion (will be erased when refcount drops to zero) */
e->ep_state |= ENTRY_STATE_DELETED;
+#if 0
+ if (slapi_is_loglevel_set(SLAPI_LOG_CACHE)) {
+ dump_hash(cache->c_idtable);
+ }
+#endif
LOG("<= entrycache_remove_int: %d\n", ret, 0, 0);
return ret;
}
@@ -999,14 +1013,23 @@ static int entrycache_replace(struct cache *cache, struct backentry *olde,
* cache tables, operation error
*/
if ( (olde->ep_state & ENTRY_STATE_NOTINCACHE) == 0 ) {
-
- found = remove_hash(cache->c_dntable, (void *)oldndn, strlen(oldndn));
- found &= remove_hash(cache->c_idtable, &(olde->ep_id), sizeof(ID));
+ int found_in_dn = remove_hash(cache->c_dntable, (void *)oldndn, strlen(oldndn));
+ int found_in_id = remove_hash(cache->c_idtable, &(olde->ep_id), sizeof(ID));
+#ifdef UUIDCACHE_ON
+ int found_in_uuid = remove_hash(cache->c_uuidtable, (void *)olduuid, strlen(olduuid));
+#endif
+ found = found_in_dn && found_in_id;
#ifdef UUIDCACHE_ON
- found &= remove_hash(cache->c_uuidtable, (void *)olduuid, strlen(olduuid));
+ found = found && found_in_uuid;
#endif
if (!found) {
- LOG("entry cache replace: cache index tables out of sync\n", 0, 0, 0);
+#ifdef UUIDCACHE_ON
+ LOG("entry cache replace: cache index tables out of sync - found dn [%d] id [%d] uuid [%d]\n",
+ found_in_dn, found_in_id, found_in_uuid);
+#else
+ LOG("entry cache replace: cache index tables out of sync - found dn [%d] id [%d]\n",
+ found_in_dn, found_in_id, 0);
+#endif
PR_Unlock(cache->c_mutex);
return 1;
}
@@ -1472,7 +1495,9 @@ int cache_lock_entry(struct cache *cache, struct backentry *e)
void cache_unlock_entry(struct cache *cache, struct backentry *e)
{
LOG("=> cache_unlock_entry\n", 0, 0, 0);
- PR_ExitMonitor(e->ep_mutexp);
+ if (PR_ExitMonitor(e->ep_mutexp)) {
+ LOG("=> cache_unlock_entry - monitor was not entered!!!\n", 0, 0, 0);
+ }
}
/* DN cache */
diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c
index 132b2b9..09d10a0 100644
--- a/ldap/servers/slapd/back-ldbm/dblayer.c
+++ b/ldap/servers/slapd/back-ldbm/dblayer.c
@@ -214,6 +214,7 @@ static int dblayer_start_deadlock_thread(struct ldbminfo *li);
static int dblayer_start_checkpoint_thread(struct ldbminfo *li);
static int dblayer_start_trickle_thread(struct ldbminfo *li);
static int dblayer_start_perf_thread(struct ldbminfo *li);
+static int dblayer_start_txn_test_thread(struct ldbminfo *li);
static int trans_batch_count=1;
static int trans_batch_limit=0;
static PRBool log_flush_thread=PR_FALSE;
@@ -226,6 +227,14 @@ static void dblayer_pop_pvt_txn();
#define MEGABYTE (1024 * 1024)
#define GIGABYTE (1024 * MEGABYTE)
+/* env. vars. you can set to stress txn handling */
+#define TXN_TESTING "TXN_TESTING" /* enables the txn test thread */
+#define TXN_TEST_HOLD_MSEC "TXN_TEST_HOLD_MSEC" /* time to hold open the db cursors */
+#define TXN_TEST_LOOP_MSEC "TXN_TEST_LOOP_MSEC" /* time to wait before looping again */
+#define TXN_TEST_USE_TXN "TXN_TEST_USE_TXN" /* use transactions or not */
+#define TXN_TEST_USE_RMW "TXN_TEST_USE_RMW" /* use DB_RMW for c_get flags or not */
+#define TXN_TEST_INDEXES "TXN_TEST_INDEXES" /* list of indexes to use - comma delimited - id2entry,entryrdn,etc. */
+#define TXN_TEST_VERBOSE "TXN_TEST_VERBOSE" /* be wordy */
/* This function compares two index keys. It is assumed
that the values are already normalized, since they should have
@@ -1755,6 +1764,9 @@ dblayer_start(struct ldbminfo *li, int dbmode)
/* Now open the performance counters stuff */
perfctrs_init(li,&(priv->perf_private));
+ if (getenv(TXN_TESTING)) {
+ dblayer_start_txn_test_thread(li);
+ }
}
if (return_value != 0) {
if (return_value == ENOMEM) {
@@ -2597,7 +2609,10 @@ int dblayer_instance_close(backend *be)
if (NULL == inst)
return -1;
- if (getenv("USE_VALGRIND")) {
+ if (!inst->import_env) {
+ be->be_state = BE_STATE_STOPPING;
+ }
+ if (getenv("USE_VALGRIND") || slapi_is_loglevel_set(SLAPI_LOG_CACHE)) {
/*
* if any string is set to an environment variable USE_VALGRIND,
* when running a memory leak checking tool (e.g., valgrind),
@@ -3422,7 +3437,7 @@ int dblayer_txn_begin_ext(struct ldbminfo *li, back_txnid parent_txn, back_txn *
return_value = TXN_BEGIN(pEnv->dblayer_DB_ENV,
(DB_TXN*)parent_txn,
&new_txn.back_txn_txn,
- 0);
+ DB_TXN_NOWAIT);
if (0 != return_value)
{
if(use_lock) slapi_rwlock_unlock(priv->dblayer_env->dblayer_env_lock);
@@ -3725,6 +3740,407 @@ dblayer_start_deadlock_thread(struct ldbminfo *li)
return return_value;
}
+static const u_int32_t default_flags = DB_NEXT;
+
+/* this is the loop delay - how long after we release the db pages
+ until we acquire them again */
+#define TXN_TEST_LOOP_WAIT(msecs) do { \
+ if (msecs) { \
+ DS_Sleep(PR_MillisecondsToInterval(slapi_rand() % msecs)); \
+ } \
+} while (0)
+
+/* this is how long we hold the pages open until we close the cursors */
+#define TXN_TEST_PAGE_HOLD(msecs) do { \
+ if (msecs) { \
+ DS_Sleep(PR_MillisecondsToInterval(slapi_rand() % msecs)); \
+ } \
+} while (0)
+
+typedef struct txn_test_iter {
+ DB *db;
+ DBC *cur;
+ size_t cnt;
+ const char *attr;
+ u_int32_t flags;
+ backend *be;
+} txn_test_iter;
+
+typedef struct txn_test_cfg {
+ PRUint32 hold_msec;
+ PRUint32 loop_msec;
+ u_int32_t flags;
+ int use_txn;
+ char **indexes;
+ int verbose;
+} txn_test_cfg;
+
+static txn_test_iter *
+new_txn_test_iter(DB *db, const char *attr, backend *be, u_int32_t flags)
+{
+ txn_test_iter *tti = (txn_test_iter *)slapi_ch_malloc(sizeof(txn_test_iter));
+ tti->db = db;
+ tti->cur = NULL;
+ tti->cnt = 0;
+ tti->attr = attr;
+ tti->flags = default_flags|flags;
+ tti->be = be;
+ return tti;
+}
+
+static void
+init_txn_test_iter(txn_test_iter *tti)
+{
+ if (tti->cur) {
+ if (tti->cur->dbp && (tti->cur->dbp->open_flags == 0x58585858)) {
+ /* already closed? */
+ } else if (tti->be && (tti->be->be_state != BE_STATE_STARTED)) {
+ /* already closed? */
+ } else {
+ tti->cur->c_close(tti->cur);
+ }
+ tti->cur = NULL;
+ }
+ tti->cnt = 0;
+ tti->flags = default_flags;
+}
+
+static void
+free_txn_test_iter(txn_test_iter *tti)
+{
+ init_txn_test_iter(tti);
+ slapi_ch_free((void **)&tti);
+}
+
+static void
+free_ttilist(txn_test_iter ***ttilist, size_t *tticnt)
+{
+ if (!ttilist || !*ttilist || !**ttilist) {
+ return;
+ }
+ while (*tticnt > 0) {
+ (*tticnt)--;
+ free_txn_test_iter((*ttilist)[*tticnt]);
+ }
+ slapi_ch_free((void *)ttilist);
+}
+
+static void
+init_ttilist(txn_test_iter **ttilist, size_t tticnt)
+{
+ if (!ttilist || !*ttilist) {
+ return;
+ }
+ while (tticnt > 0) {
+ tticnt--;
+ init_txn_test_iter(ttilist[tticnt]);
+ }
+}
+
+static void
+print_ttilist(txn_test_iter **ttilist, size_t tticnt)
+{
+ while (tticnt > 0) {
+ tticnt--;
+ LDAPDebug2Args(LDAP_DEBUG_ANY,
+ "txn_test_threadmain: attr [%s] cnt [%lu]\n",
+ ttilist[tticnt]->attr, ttilist[tticnt]->cnt);
+ }
+}
+
+#define TXN_TEST_IDX_OK_IF_NULL "nscpEntryDN"
+
+static void
+txn_test_init_cfg(txn_test_cfg *cfg)
+{
+ static char *indexlist = "aci,entryrdn,numsubordinates,uid,ancestorid,objectclass,uniquemember,cn,parentid,nsuniqueid,sn,id2entry," TXN_TEST_IDX_OK_IF_NULL;
+ char *indexlist_copy = NULL;
+
+ cfg->hold_msec = getenv(TXN_TEST_HOLD_MSEC) ? atoi(getenv(TXN_TEST_HOLD_MSEC)) : 200;
+ cfg->loop_msec = getenv(TXN_TEST_LOOP_MSEC) ? atoi(getenv(TXN_TEST_LOOP_MSEC)) : 10;
+ cfg->flags = getenv(TXN_TEST_USE_RMW) ? DB_RMW : 0;
+ cfg->use_txn = getenv(TXN_TEST_USE_TXN) ? 1 : 0;
+ if (getenv(TXN_TEST_INDEXES)) {
+ indexlist_copy = slapi_ch_strdup(getenv(TXN_TEST_INDEXES));
+ } else {
+ indexlist_copy = slapi_ch_strdup(indexlist);
+ }
+ cfg->indexes = slapi_str2charray(indexlist_copy, ",");
+ slapi_ch_free_string(&indexlist_copy);
+ cfg->verbose = getenv(TXN_TEST_VERBOSE) ? 1 : 0;
+
+ slapi_log_error(SLAPI_LOG_FATAL, "txn_test_threadmain",
+ "Config hold_msec [%d] loop_msec [%d] rmw [%d] txn [%d] indexes [%s]\n",
+ cfg->hold_msec, cfg->loop_msec, cfg->flags, cfg->use_txn,
+ getenv(TXN_TEST_INDEXES) ? getenv(TXN_TEST_INDEXES) : indexlist);
+}
+
+static int txn_test_threadmain(void *param)
+{
+ dblayer_private *priv = NULL;
+ struct ldbminfo *li = NULL;
+ Object *inst_obj;
+ int rc = 0;
+ txn_test_iter **ttilist = NULL;
+ size_t tticnt = 0;
+ DB_TXN *txn = NULL;
+ txn_test_cfg cfg;
+ size_t counter = 0;
+ char keybuf[8192];
+ char databuf[8192];
+
+ PR_ASSERT(NULL != param);
+ li = (struct ldbminfo*)param;
+
+ priv = (dblayer_private*)li->li_dblayer_private;
+ PR_ASSERT(NULL != priv);
+
+ INCR_THREAD_COUNT(priv);
+
+ if (!priv->dblayer_enable_transactions) {
+ goto end;
+ }
+
+ txn_test_init_cfg(&cfg);
+
+wait_for_init:
+ free_ttilist(&ttilist, &tticnt);
+ DS_Sleep(PR_MillisecondsToInterval(1000));
+ if (priv->dblayer_stop_threads) {
+ goto end;
+ }
+
+ for (inst_obj = objset_first_obj(li->li_instance_set); inst_obj;
+ inst_obj = objset_next_obj(li->li_instance_set, inst_obj)) {
+ char **idx = NULL;
+ ldbm_instance *inst = (ldbm_instance *)object_get_data(inst_obj);
+ backend *be = inst->inst_be;
+
+ if (be->be_state != BE_STATE_STARTED) {
+ object_release(inst_obj);
+ goto wait_for_init;
+ }
+
+ for (idx = cfg.indexes; idx && *idx; ++idx) {
+ DB *db = NULL;
+ if (be->be_state != BE_STATE_STARTED) {
+ object_release(inst_obj);
+ goto wait_for_init;
+ }
+
+ if (!strcmp(*idx, "id2entry")) {
+ dblayer_get_id2entry(be, &db);
+ if (db == NULL) {
+ object_release(inst_obj);
+ goto wait_for_init;
+ }
+ } else {
+ struct attrinfo *ai = NULL;
+ ainfo_get(be, *idx, &ai);
+ if (NULL == ai) {
+ object_release(inst_obj);
+ goto wait_for_init;
+ }
+ dblayer_get_index_file(be, ai, &db, 0);
+ if (NULL == db) {
+ if (strcasecmp(*idx, TXN_TEST_IDX_OK_IF_NULL)) {
+ object_release(inst_obj);
+ goto wait_for_init;
+ }
+ }
+ }
+ if (db) {
+ ttilist = (txn_test_iter **)slapi_ch_realloc((char *)ttilist, sizeof(txn_test_iter *) * (tticnt + 1));
+ ttilist[tticnt++] = new_txn_test_iter(db, *idx, be, cfg.flags);
+ }
+ }
+ }
+
+ while (!priv->dblayer_stop_threads) {
+retry_txn:
+ init_ttilist(ttilist, tticnt);
+ if (txn) {
+ TXN_ABORT(txn);
+ txn = NULL;
+ }
+ if (cfg.use_txn) {
+ rc = TXN_BEGIN(priv->dblayer_env->dblayer_DB_ENV, NULL, &txn, 0);
+ if (rc || !txn) {
+ LDAPDebug2Args(LDAP_DEBUG_ANY,
+ "txn_test_threadmain failed to create a new transaction, err=%d (%s)\n",
+ rc, dblayer_strerror(rc));
+ }
+ } else {
+ rc = 0;
+ }
+ if (!rc) {
+ DBT key;
+ DBT data;
+ size_t ii;
+ size_t donecnt = 0;
+ size_t cnt = 0;
+
+ /* phase 1 - open a cursor to each db */
+ if (cfg.verbose) {
+ LDAPDebug1Arg(LDAP_DEBUG_ANY,
+ "txn_test_threadmain: starting [%lu] indexes\n", tticnt);
+ }
+ for (ii = 0; ii < tticnt; ++ii) {
+ txn_test_iter *tti = ttilist[ii];
+
+retry_cursor:
+ if (priv->dblayer_stop_threads) {
+ goto end;
+ }
+ if (tti->be->be_state != BE_STATE_STARTED) {
+ if (txn) {
+ TXN_ABORT(txn);
+ txn = NULL;
+ }
+ goto wait_for_init;
+ }
+ if (tti->db->open_flags == 0xdbdbdbdb) {
+ if (txn) {
+ TXN_ABORT(txn);
+ txn = NULL;
+ }
+ goto wait_for_init;
+ }
+ rc = tti->db->cursor(tti->db, txn, &tti->cur, 0);
+ if (DB_LOCK_DEADLOCK == rc) {
+ if (cfg.verbose) {
+ LDAPDebug0Args(LDAP_DEBUG_ANY,
+ "txn_test_threadmain cursor create deadlock - retry\n");
+ }
+ if (cfg.use_txn) {
+ goto retry_txn;
+ } else {
+ goto retry_cursor;
+ }
+ } else if (rc) {
+ LDAPDebug2Args(LDAP_DEBUG_ANY,
+ "txn_test_threadmain failed to create a new cursor, err=%d (%s)\n",
+ rc, dblayer_strerror(rc));
+ }
+ }
+
+ memset(&key, 0, sizeof(key));
+ key.flags = DB_DBT_USERMEM;
+ key.data = keybuf;
+ key.ulen = sizeof(keybuf);
+ memset(&data, 0, sizeof(data));
+ data.flags = DB_DBT_USERMEM;
+ data.data = databuf;
+ data.ulen = sizeof(databuf);
+ /* phase 2 - iterate over each cursor at the same time until
+ 1) get error
+ 2) get deadlock
+ 3) all cursors are exhausted
+ */
+ while (donecnt < tticnt) {
+ for (ii = 0; ii < tticnt; ++ii) {
+ txn_test_iter *tti = ttilist[ii];
+ if (tti->cur) {
+retry_get:
+ if (priv->dblayer_stop_threads) {
+ goto end;
+ }
+ if (tti->be->be_state != BE_STATE_STARTED) {
+ if (txn) {
+ TXN_ABORT(txn);
+ txn = NULL;
+ }
+ goto wait_for_init;
+ }
+ if (tti->db->open_flags == 0xdbdbdbdb) {
+ if (txn) {
+ TXN_ABORT(txn);
+ txn = NULL;
+ }
+ goto wait_for_init;
+ }
+ rc = tti->cur->c_get(tti->cur, &key, &data, tti->flags);
+ if (DB_LOCK_DEADLOCK == rc) {
+ if (cfg.verbose) {
+ LDAPDebug0Args(LDAP_DEBUG_ANY,
+ "txn_test_threadmain cursor get deadlock - retry\n");
+ }
+ if (cfg.use_txn) {
+ goto retry_txn;
+ } else {
+ goto retry_get;
+ }
+ } else if (DB_NOTFOUND == rc) {
+ donecnt++; /* ran out of this one */
+ tti->flags = DB_FIRST|cfg.flags; /* start over until all indexes are done */
+ } else if (rc) {
+ if ((DB_BUFFER_SMALL != rc) || cfg.verbose) {
+ LDAPDebug2Args(LDAP_DEBUG_ANY,
+ "txn_test_threadmain failed to read a cursor, err=%d (%s)\n",
+ rc, dblayer_strerror(rc));
+ }
+ tti->cur->c_close(tti->cur);
+ tti->cur = NULL;
+ donecnt++;
+ } else {
+ tti->cnt++;
+ tti->flags = default_flags|cfg.flags;
+ cnt++;
+ }
+ }
+ }
+ }
+ TXN_TEST_PAGE_HOLD(cfg.hold_msec);
+ /*print_ttilist(ttilist, tticnt);*/
+ init_ttilist(ttilist, tticnt);
+ if (cfg.verbose) {
+ LDAPDebug2Args(LDAP_DEBUG_ANY,
+ "txn_test_threadmain: finished [%lu] indexes [%lu] records\n", tticnt, cnt);
+ }
+ TXN_TEST_LOOP_WAIT(cfg.loop_msec);
+ } else {
+ TXN_TEST_LOOP_WAIT(cfg.loop_msec);
+ }
+ counter++;
+ if (!(counter % 40)) {
+ /* some operations get completely stuck - so every once in a while,
+ pause to allow those ops to go through */
+ DS_Sleep(PR_SecondsToInterval(1));
+ }
+ }
+
+end:
+ slapi_ch_array_free(cfg.indexes);
+ free_ttilist(&ttilist, &tticnt);
+ if (txn) {
+ TXN_ABORT(txn);
+ }
+ DECR_THREAD_COUNT(priv);
+ return 0;
+}
+
+/*
+ * create a thread for transaction deadlock testing
+ */
+static int
+dblayer_start_txn_test_thread(struct ldbminfo *li)
+{
+ int return_value = 0;
+ if (NULL == PR_CreateThread (PR_USER_THREAD,
+ (VFP) (void *) txn_test_threadmain, li,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ SLAPD_DEFAULT_THREAD_STACKSIZE) )
+ {
+ PRErrorCode prerr = PR_GetError();
+ LDAPDebug(LDAP_DEBUG_ANY, "failed to create txn test thread, "
+ SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
+ prerr, slapd_pr_strerror(prerr), 0);
+ return_value = -1;
+ }
+ return return_value;
+}
+
/* deadlock thread main function */
static int deadlock_threadmain(void *param)
diff --git a/ldap/servers/slapd/back-ldbm/index.c b/ldap/servers/slapd/back-ldbm/index.c
index 7e8aa12..cfcd51f 100644
--- a/ldap/servers/slapd/back-ldbm/index.c
+++ b/ldap/servers/slapd/back-ldbm/index.c
@@ -412,7 +412,7 @@ index_addordel_entry(
}
result = index_addordel_string(be, SLAPI_ATTR_NSCP_ENTRYDN, slapi_sdn_get_ndn(&parent), e->ep_id, flags, txn);
if ( result != 0 ) {
- ldbm_nasty(errmsg, 1020, result);
+ ldbm_nasty(errmsg, 1021, result);
return( result );
}
slapi_sdn_done(&parent);
@@ -423,6 +423,7 @@ index_addordel_entry(
*/
result = entryrdn_index_entry(be, e, flags, txn);
if ( result != 0 ) {
+ ldbm_nasty(errmsg, 1023, result);
return( result );
}
/* To maintain tombstonenumsubordinates,
@@ -433,7 +434,7 @@ index_addordel_entry(
result = index_addordel_values_sv(be, LDBM_PARENTID_STR, svals, NULL,
e->ep_id, flags, txn);
if ( result != 0 ) {
- ldbm_nasty(errmsg, 1020, result);
+ ldbm_nasty(errmsg, 1022, result);
return( result );
}
}
@@ -481,6 +482,7 @@ index_addordel_entry(
if (entryrdn_get_switch()) { /* subtree-rename: on */
result = entryrdn_index_entry(be, e, flags, txn);
if ( result != 0 ) {
+ ldbm_nasty(errmsg, 1031, result);
return( result );
}
}
@@ -608,13 +610,18 @@ index_add_mods(
/* We need to first remove the old values from the
* index, if any. */
if (deleted_valueArray) {
- index_addordel_values_sv( be, mods[i]->mod_type,
- deleted_valueArray, evals, id,
- flags, txn );
+ rc = index_addordel_values_sv( be, mods[i]->mod_type,
+ deleted_valueArray, evals, id,
+ flags, txn );
+ if (rc) {
+ ldbm_nasty(errmsg, 1041, rc);
+ goto error;
+ }
}
/* Free valuearray */
slapi_valueset_free(mod_vals);
+ mod_vals = NULL;
case LDAP_MOD_ADD:
if ( mods_valueArray == NULL ) {
rc = 0;
@@ -643,9 +650,13 @@ index_add_mods(
}
if (mods_valueArray) {
rc = index_addordel_values_sv( be,
- mods[i]->mod_type,
- mods_valueArray, NULL,
- id, BE_INDEX_ADD, txn );
+ mods[i]->mod_type,
+ mods_valueArray, NULL,
+ id, BE_INDEX_ADD, txn );
+ if (rc) {
+ ldbm_nasty(errmsg, 1042, rc);
+ goto error;
+ }
} else {
rc = 0;
}
@@ -702,12 +713,17 @@ index_add_mods(
/* Update the index, if necessary */
if (deleted_valueArray) {
- index_addordel_values_sv( be, mods[i]->mod_type,
- deleted_valueArray, evals, id,
- flags, txn );
+ rc = index_addordel_values_sv( be, mods[i]->mod_type,
+ deleted_valueArray, evals, id,
+ flags, txn );
+ if (rc) {
+ ldbm_nasty(errmsg, 1043, rc);
+ goto error;
+ }
}
slapi_valueset_free(mod_vals);
+ mod_vals = NULL;
} else {
/* determine if the presence key should be
@@ -753,15 +769,25 @@ index_add_mods(
rc = index_addordel_values_sv( be, basetype,
mods_valueArray,
evals, id, flags, txn );
+ if (rc) {
+ ldbm_nasty(errmsg, 1044, rc);
+ goto error;
+ }
}
rc = 0;
break;
} /* switch ( mods[i]->mod_op & ~LDAP_MOD_BVALUES ) */
+error:
/* free memory */
slapi_ch_free((void **)&tmp);
+ tmp = NULL;
valuearray_free(&mods_valueArray);
+ mods_valueArray = NULL;
slapi_valueset_free(all_vals);
+ all_vals = NULL;
+ slapi_valueset_free(mod_vals);
+ mod_vals = NULL;
if ( rc != 0 ) {
ldbm_nasty(errmsg, 1040, rc);
@@ -996,6 +1022,9 @@ index_read_ext_allids(
idl = idl_fetch_ext( be, db, &key, db_txn, ai, err, allidslimit );
if(*err == DB_LOCK_DEADLOCK) {
ldbm_nasty("index read retrying transaction", 1045, *err);
+#ifdef FIX_TXN_DEADLOCKS
+#error can only retry here if txn == NULL - otherwise, have to abort and retry txn
+#endif
continue;
} else {
break;
@@ -1124,6 +1153,9 @@ retry:
cursor->c_close(cursor);
cursor = NULL;
key->data = saved_key;
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to abort and retry the transaction, not just the cursor
+#endif
goto retry;
} else
{
@@ -1146,6 +1178,9 @@ retry:
cursor->c_close(cursor);
cursor = NULL;
key->data = saved_key;
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to abort and retry the transaction, not just the cursor
+#endif
goto retry;
}
error:
@@ -1493,6 +1528,9 @@ index_range_read_ext(
tmp = idl_fetch_ext( be, db, &cur_key, NULL, ai, err, allidslimit );
if(*err == DB_LOCK_DEADLOCK) {
ldbm_nasty("index_range_read retrying transaction", 1090, *err);
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to abort and retry the transaction, not just the fetch
+#endif
continue;
} else {
break;
@@ -1641,7 +1679,7 @@ addordel_values(
if ( rc != 0)
{
- ldbm_nasty(errmsg, 1090, rc);
+ ldbm_nasty(errmsg, 1096, rc);
}
index_free_prefix (prefix);
if (NULL != key.dptr && prefix != key.dptr)
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c
index 1539c7c..18390c2 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c
@@ -934,7 +934,7 @@ ldbm_back_add( Slapi_PBlock *pb )
if (retry_count == RETRY_TIMES) {
/* Failed */
LDAPDebug( LDAP_DEBUG_ANY, "Retry count exceeded in add\n", 0, 0, 0 );
- ldap_result_code= LDAP_OPERATIONS_ERROR;
+ ldap_result_code= LDAP_BUSY;
goto error_return;
}
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
index 57a4605..237085c 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
@@ -60,7 +60,8 @@ ldbm_back_delete( Slapi_PBlock *pb )
struct ldbminfo *li = NULL;
struct backentry *e = NULL;
struct backentry *tombstone = NULL;
- struct backentry *original_entry = NULL;
+ Slapi_Entry *original_entry = NULL;
+ struct backentry *original_tombstone = NULL;
char *dn = NULL;
back_txn txn;
back_txnid parent_txn;
@@ -90,7 +91,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
int delete_tombstone_entry = 0; /* We must remove the given tombstone entry from the DB */
int create_tombstone_entry = 0; /* We perform a "regular" LDAP delete but since we use */
/* replication, we must create a new tombstone entry */
- int e_in_cache = 0;
int tombstone_in_cache = 0;
entry_address *addr;
int addordel_flags = 0; /* passed to index_addordel */
@@ -98,6 +98,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
Slapi_Entry *orig_entry = NULL;
Slapi_DN parentsdn;
int opreturn = 0;
+ int free_delete_existing_entry = 0;
slapi_pblock_get( pb, SLAPI_BACKEND, &be);
slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
@@ -186,7 +187,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
/* retval is -1 */
goto error_return; /* error result sent by find_entry2modify() */
}
- e_in_cache = 1;
if ( slapi_entry_has_children( e->ep_entry ) )
{
@@ -206,6 +206,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
*/
ldap_result_code= get_copy_of_entry(pb, addr, &txn,
SLAPI_DELETE_EXISTING_ENTRY, !is_replicated_operation);
+ free_delete_existing_entry = 1;
if(ldap_result_code==LDAP_OPERATIONS_ERROR ||
ldap_result_code==LDAP_INVALID_DN_SYNTAX)
{
@@ -428,6 +429,11 @@ ldbm_back_delete( Slapi_PBlock *pb )
slapi_value_free(&tomb_value);
/* XXXggood above used to be: slapi_entry_add_string(tombstone->ep_entry, SLAPI_ATTR_OBJECTCLASS, SLAPI_ATTR_VALUE_TOMBSTONE); */
/* JCMREPL - Add a description of what's going on? */
+
+ if ( (original_tombstone = backentry_dup( tombstone )) == NULL ) {
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ goto error_return;
+ }
}
if (!is_ruv && !is_fixup_operation && !delete_tombstone_entry) {
@@ -443,7 +449,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
}
}
- if ( (original_entry = backentry_dup( e )) == NULL ) {
+ if ( (original_entry = slapi_entry_dup( e->ep_entry )) == NULL ) {
ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
}
@@ -456,26 +462,45 @@ ldbm_back_delete( Slapi_PBlock *pb )
txn.back_txn_txn = NULL; /* ready to create the child transaction */
for (retry_count = 0; retry_count < RETRY_TIMES; retry_count++) {
if (txn.back_txn_txn && (txn.back_txn_txn != parent_txn)) {
+ Slapi_Entry *ent = NULL;
+
dblayer_txn_abort(li,&txn);
slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
- if (e_in_cache) {
- /* entry 'e' is in the entry cache. Since we reset 'e' to
- * the original_entry, remove it from the cache. */
- CACHE_REMOVE(&inst->inst_cache, e);
- cache_unlock_entry(&inst->inst_cache, e);
- CACHE_RETURN(&inst->inst_cache, &e);
- /* As we are about to delete it,
- * we don't put the entry back to cache */
- e_in_cache = 0;
- } else {
- backentry_free(&e);
+
+ /* reset original entry */
+ slapi_pblock_get( pb, SLAPI_DELETE_EXISTING_ENTRY, &ent );
+ if (ent && (ent != original_entry) && free_delete_existing_entry) {
+ slapi_entry_free(ent);
+ slapi_pblock_set( pb, SLAPI_DELETE_EXISTING_ENTRY, NULL );
}
- slapi_pblock_set( pb, SLAPI_DELETE_EXISTING_ENTRY, original_entry->ep_entry );
- e = original_entry;
- if ( (original_entry = backentry_dup( e )) == NULL ) {
+ slapi_entry_free(e->ep_entry);
+ e->ep_entry = original_entry;
+ if ( (original_entry = slapi_entry_dup( e->ep_entry )) == NULL ) {
ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
}
+ slapi_pblock_set( pb, SLAPI_DELETE_EXISTING_ENTRY, original_entry );
+ free_delete_existing_entry = 0; /* owned by original_entry now */
+ if (nscpEntrySDN) {
+ nscpEntrySDN = slapi_entry_get_sdn(original_entry);
+ }
+
+ /* reset tombstone entry */
+ if (original_tombstone) {
+ if (tombstone_in_cache) {
+ CACHE_REMOVE(&inst->inst_cache, tombstone);
+ CACHE_RETURN(&inst->inst_cache, &tombstone);
+ tombstone_in_cache = 0;
+ } else {
+ backentry_free(&tombstone);
+ }
+ tombstone = original_tombstone;
+ if ( (original_tombstone = backentry_dup( tombstone )) == NULL ) {
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ goto error_return;
+ }
+ }
+
/* We're re-trying */
LDAPDebug0Args(LDAP_DEBUG_BACKLDBM,
"Delete Retrying Transaction\n");
@@ -562,6 +587,14 @@ ldbm_back_delete( Slapi_PBlock *pb )
* tentatively for now, then cache_add again when the original
* entry is removed from the cache.
*/
+ if (cache_add_tentative( &inst->inst_cache, tombstone, NULL) == 0) {
+ tombstone_in_cache = 1;
+ } else if (!(tombstone->ep_state & ENTRY_STATE_NOTINCACHE)) {
+ LDAPDebug1Arg(LDAP_DEBUG_CACHE,
+ "id2entry_add tombstone (%s) is in cache\n",
+ slapi_entry_get_dn(tombstone->ep_entry));
+ tombstone_in_cache = 1;
+ }
retval = id2entry_add( be, tombstone, &txn );
if (DB_LOCK_DEADLOCK == retval) {
LDAPDebug( LDAP_DEBUG_ARGS, "delete 1 DB_LOCK_DEADLOCK\n", 0, 0, 0 );
@@ -576,14 +609,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
LDAP_OPERATIONS_ERROR, retry_count);
goto error_return;
}
- if (cache_add_tentative( &inst->inst_cache, tombstone, NULL) == 0) {
- tombstone_in_cache = 1;
- } else if (!(tombstone->ep_state & ENTRY_STATE_NOTINCACHE)) {
- LDAPDebug1Arg(LDAP_DEBUG_CACHE,
- "id2entry_add tombstone (%s) is in cache\n",
- slapi_entry_get_dn(tombstone->ep_entry));
- tombstone_in_cache = 1;
- }
}
else
{
@@ -966,7 +991,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
if (retry_count == RETRY_TIMES) {
/* Failed */
LDAPDebug( LDAP_DEBUG_ANY, "Retry count exceeded in delete\n", 0, 0, 0 );
- ldap_result_code= LDAP_OPERATIONS_ERROR;
+ ldap_result_code= LDAP_BUSY;
retval = -1;
goto error_return;
}
@@ -1007,18 +1032,13 @@ ldbm_back_delete( Slapi_PBlock *pb )
}
/* delete from cache and clean up */
- if (e_in_cache) {
+ if (e) {
CACHE_REMOVE(&inst->inst_cache, e);
cache_unlock_entry(&inst->inst_cache, e);
CACHE_RETURN(&inst->inst_cache, &e);
+ e = NULL;
}
- if (tombstone_in_cache) {
- if (CACHE_ADD( &inst->inst_cache, tombstone, NULL ) == 0) {
- tombstone_in_cache = 1;
- } else {
- tombstone_in_cache = 0;
- }
- }
+
if (parent_found)
{
/* Replace the old parent entry with the newly modified one */
@@ -1042,6 +1062,9 @@ error_return:
if (tombstone_in_cache)
{
CACHE_REMOVE( &inst->inst_cache, tombstone );
+ CACHE_RETURN( &inst->inst_cache, &tombstone );
+ tombstone = NULL;
+ tombstone_in_cache = 0;
}
else
{
@@ -1108,6 +1131,8 @@ common_return:
if (tombstone_in_cache)
{
CACHE_RETURN( &inst->inst_cache, &tombstone );
+ tombstone = NULL;
+ tombstone_in_cache = 0;
}
else
{
@@ -1126,7 +1151,7 @@ common_return:
/* Need to return to cache after post op plugins are called */
if (retval) { /* error case */
- if (e && e_in_cache) {
+ if (e) {
cache_unlock_entry( &inst->inst_cache, e );
CACHE_RETURN( &inst->inst_cache, &e );
}
@@ -1156,8 +1181,13 @@ diskfull_return:
*/
slapi_pblock_set(pb, SLAPI_URP_NAMING_COLLISION_DN, slapi_ch_strdup (dn));
}
- done_with_pblock_entry(pb, SLAPI_DELETE_EXISTING_ENTRY);
- backentry_free(&original_entry);
+ if (free_delete_existing_entry) {
+ done_with_pblock_entry(pb, SLAPI_DELETE_EXISTING_ENTRY);
+ } else { /* owned by original_entry */
+ slapi_pblock_set(pb, SLAPI_DELETE_EXISTING_ENTRY, NULL);
+ }
+ slapi_entry_free(original_entry);
+ backentry_free(&original_tombstone);
slapi_ch_free((void**)&errbuf);
slapi_sdn_done(&sdn);
slapi_ch_free_string(&e_uniqueid);
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
index b548b29..449e02a 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
@@ -115,8 +115,8 @@ static char *_entryrdn_decrypt_key(backend *be, const char *key, struct attrinfo
#endif
static int _entryrdn_get_elem(DBC *cursor, DBT *key, DBT *data, const char *comp_key, rdn_elem **elem);
static int _entryrdn_get_tombstone_elem(DBC *cursor, Slapi_RDN *srdn, DBT *key, const char *comp_key, rdn_elem **elem);
-static int _entryrdn_put_data(DBC *cursor, DBT *key, DBT *data, char type);
-static int _entryrdn_del_data(DBC *cursor, DBT *key, DBT *data);
+static int _entryrdn_put_data(DBC *cursor, DBT *key, DBT *data, char type, DB_TXN *db_txn);
+static int _entryrdn_del_data(DBC *cursor, DBT *key, DBT *data, DB_TXN *db_txn);
static int _entryrdn_insert_key(backend *be, DBC *cursor, Slapi_RDN *srdn, ID id, DB_TXN *db_txn);
static int _entryrdn_insert_key_elems(backend *be, DBC *cursor, Slapi_RDN *srdn, DBT *key, rdn_elem *elem, rdn_elem *childelem, size_t childelemlen, DB_TXN *db_txn);
static int _entryrdn_delete_key(backend *be, DBC *cursor, Slapi_RDN *srdn, ID id, DB_TXN *db_txn);
@@ -274,7 +274,7 @@ entryrdn_index_entry(backend *be,
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_index_entry: Failed to make a cursor: %s(%d)\n",
dblayer_strerror(rc), rc);
- if (DB_LOCK_DEADLOCK == rc) {
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
@@ -284,6 +284,12 @@ entryrdn_index_entry(backend *be,
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "entryrdn_index_entry: cursor open failed after [%d] retries\n", db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ goto bail;
+ }
if (flags & BE_INDEX_ADD) {
rc = _entryrdn_insert_key(be, cursor, srdn, e->ep_id, db_txn);
@@ -303,7 +309,7 @@ bail:
slapi_log_error(ENTRYRDN_LOGLEVEL(myrc), ENTRYRDN_TAG,
"entryrdn_index_entry: Failed to close cursor: %s(%d)\n",
dblayer_strerror(myrc), myrc);
- if (DB_LOCK_DEADLOCK == myrc) {
+ if ((DB_LOCK_DEADLOCK == myrc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
@@ -317,6 +323,11 @@ bail:
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "entryrdn_index_entry: cursor close failed after [%d] retries\n", db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ }
}
if (db) {
dblayer_release_index_file(be, ai, db);
@@ -407,7 +418,7 @@ entryrdn_index_read_ext(backend *be,
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_index_read: Failed to make a cursor: %s(%d)\n",
dblayer_strerror(rc), rc);
- if (DB_LOCK_DEADLOCK == rc) {
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
@@ -417,6 +428,13 @@ entryrdn_index_read_ext(backend *be,
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "entryrdn_index_read: Failed to make a cursor after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ goto bail;
+ }
rc = _entryrdn_index_read(be, cursor, &srdn, &elem, NULL, NULL,
flags, db_txn);
@@ -434,7 +452,7 @@ bail:
slapi_log_error(ENTRYRDN_LOGLEVEL(myrc), ENTRYRDN_TAG,
"entryrdn_index_read: Failed to close cursor: %s(%d)\n",
dblayer_strerror(myrc), myrc);
- if (DB_LOCK_DEADLOCK == myrc) {
+ if ((DB_LOCK_DEADLOCK == myrc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
@@ -448,6 +466,12 @@ bail:
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "entryrdn_index_read: Failed to close cursor after [%d] retries\n",
+ db_retry);
+ rc = rc ? rc : DB_LOCK_DEADLOCK;
+ }
}
if (db) {
dblayer_release_index_file(be, ai, db);
@@ -594,7 +618,7 @@ entryrdn_rename_subtree(backend *be,
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_rename_subtree: Failed to make a cursor: %s(%d)\n",
dblayer_strerror(rc), rc);
- if (DB_LOCK_DEADLOCK == rc) {
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
@@ -604,6 +628,13 @@ entryrdn_rename_subtree(backend *be,
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "entryrdn_rename_subtree: create cursor failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ goto bail;
+ }
/* prepare the element for the newly renamed rdn, if any. */
if (mynewsrdn) {
@@ -680,7 +711,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.ulen = renamedata.size = targetelemlen;
renamedata.data = (void *)targetelem;
renamedata.flags = DB_DBT_USERMEM;
- rc = _entryrdn_del_data(cursor, &key, &renamedata);
+ rc = _entryrdn_del_data(cursor, &key, &renamedata, db_txn);
if (rc) {
goto bail;
}
@@ -697,7 +728,7 @@ entryrdn_rename_subtree(backend *be,
_entryrdn_rdn_elem_size(*cep);
renamedata.data = (void *)(*cep);
renamedata.flags = DB_DBT_USERMEM;
- rc = _entryrdn_del_data(cursor, &key, &renamedata);
+ rc = _entryrdn_del_data(cursor, &key, &renamedata, db_txn);
if (rc) {
goto bail;
}
@@ -715,7 +746,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.ulen = renamedata.size = newelemlen;
renamedata.data = (void *)newelem;
renamedata.flags = DB_DBT_USERMEM;
- rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_SELF);
+ rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_SELF, db_txn);
if (rc) {
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_rename_subtree: Adding %s failed; "
@@ -736,7 +767,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.data = (void *)(*cep);
renamedata.flags = DB_DBT_USERMEM;
rc = _entryrdn_put_data(cursor, &key,
- &renamedata, RDN_INDEX_CHILD);
+ &renamedata, RDN_INDEX_CHILD, db_txn);
if (rc) {
goto bail;
}
@@ -755,7 +786,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.ulen = renamedata.size = oldsupelemlen;
renamedata.data = (void *)oldsupelem;
renamedata.flags = DB_DBT_USERMEM;
- rc = _entryrdn_del_data(cursor, &key, &renamedata);
+ rc = _entryrdn_del_data(cursor, &key, &renamedata, db_txn);
if (rc) {
goto bail;
}
@@ -787,7 +818,7 @@ entryrdn_rename_subtree(backend *be,
goto bail;
}
}
- rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_PARENT);
+ rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_PARENT, db_txn);
if (rc) {
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_rename_subtree: Adding "
@@ -812,7 +843,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.ulen = renamedata.size = targetelemlen;
renamedata.data = (void *)targetelem;
renamedata.flags = DB_DBT_USERMEM;
- rc = _entryrdn_del_data(cursor, &key, &renamedata);
+ rc = _entryrdn_del_data(cursor, &key, &renamedata, db_txn);
if (rc) {
goto bail;
}
@@ -822,7 +853,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.ulen = renamedata.size = newelemlen;
renamedata.data = (void *)newelem;
renamedata.flags = DB_DBT_USERMEM;
- rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_SELF);
+ rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_SELF, db_txn);
if (rc) {
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_rename_subtree: Adding %s failed; "
@@ -846,7 +877,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.ulen = renamedata.size = targetelemlen;
renamedata.data = (void *)targetelem;
renamedata.flags = DB_DBT_USERMEM;
- rc = _entryrdn_del_data(cursor, &key, &renamedata);
+ rc = _entryrdn_del_data(cursor, &key, &renamedata, db_txn);
if (rc) {
goto bail;
}
@@ -881,7 +912,7 @@ entryrdn_rename_subtree(backend *be,
goto bail;
}
}
- rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_CHILD);
+ rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_CHILD, db_txn);
if (rc) {
goto bail;
}
@@ -911,7 +942,7 @@ bail:
slapi_log_error(ENTRYRDN_LOGLEVEL(myrc), ENTRYRDN_TAG,
"entryrdn_rename_subtree: Failed to close cursor: %s(%d)\n",
dblayer_strerror(myrc), myrc);
- if (DB_LOCK_DEADLOCK == myrc) {
+ if ((DB_LOCK_DEADLOCK == myrc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
@@ -925,6 +956,12 @@ bail:
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "entryrdn_rename_subtree: Failed to close cursor after [%d] retries.\n",
+ db_retry);
+ rc = rc ? rc : DB_LOCK_DEADLOCK;
+ }
}
if (db) {
dblayer_release_index_file(be, ai, db);
@@ -1017,7 +1054,7 @@ entryrdn_get_subordinates(backend *be,
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_get_subordinates: Failed to make a cursor: %s(%d)\n",
dblayer_strerror(rc), rc);
- if (DB_LOCK_DEADLOCK == rc) {
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
@@ -1027,6 +1064,13 @@ entryrdn_get_subordinates(backend *be,
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "entryrdn_get_subordinates: Failed to make a cursor after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ goto bail;
+ }
rc = _entryrdn_index_read(be, cursor, &srdn, &elem,
NULL, &childelems, 0/*flags*/, db_txn);
@@ -1076,7 +1120,7 @@ bail:
slapi_log_error(ENTRYRDN_LOGLEVEL(myrc), ENTRYRDN_TAG,
"entryrdn_get_subordinates: Failed to close cursor: %s(%d)\n",
dblayer_strerror(myrc), myrc);
- if (DB_LOCK_DEADLOCK == myrc) {
+ if ((DB_LOCK_DEADLOCK == myrc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
@@ -1090,6 +1134,14 @@ bail:
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "entryrdn_get_subordinates: Failed to close cursor after [%d] retries\n",
+ db_retry);
+ rc = rc ? rc : DB_LOCK_DEADLOCK;
+ goto bail;
+ }
+
}
if (db) {
dblayer_release_index_file(be, ai, db);
@@ -1159,6 +1211,9 @@ entryrdn_lookup_dn(backend *be,
"entryrdn_lookup_dn: Failed to make a cursor: %s(%d)\n",
dblayer_strerror(rc), rc);
if (DB_LOCK_DEADLOCK == rc) {
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
ENTRYRDN_DELAY;
continue;
}
@@ -1199,6 +1254,11 @@ retry_get0:
if (rc) {
if (DB_LOCK_DEADLOCK == rc) {
/* try again */
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "entryrdn_get_parent: cursor get deadlock\n");
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
goto retry_get0;
} else if (DB_NOTFOUND == rc) { /* could be a suffix or
note: no parent for suffix */
@@ -1212,6 +1272,11 @@ retry_get1:
if (rc) {
if (DB_LOCK_DEADLOCK == rc) {
/* try again */
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "entryrdn_get_parent: retry cursor get deadlock\n");
goto retry_get1;
} else if (DB_NOTFOUND != rc) {
_entryrdn_cursor_print_error("entryrdn_lookup_dn",
@@ -1264,6 +1329,9 @@ bail:
"entryrdn_lookup_dn: Failed to close cursor: %s(%d)\n",
dblayer_strerror(myrc), myrc);
if (DB_LOCK_DEADLOCK == myrc) {
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
ENTRYRDN_DELAY;
continue;
}
@@ -1352,6 +1420,9 @@ entryrdn_get_parent(backend *be,
"entryrdn_get_parent: Failed to make a cursor: %s(%d)\n",
dblayer_strerror(rc), rc);
if (DB_LOCK_DEADLOCK == rc) {
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
ENTRYRDN_DELAY;
continue;
}
@@ -1388,6 +1459,11 @@ retry_get0:
rc = cursor->c_get(cursor, &key, &data, DB_SET);
if (rc) {
if (DB_LOCK_DEADLOCK == rc) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "entryrdn_get_parent: cursor get deadlock\n");
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
/* try again */
goto retry_get0;
} else if (DB_NOTFOUND == rc) { /* could be a suffix
@@ -1402,6 +1478,11 @@ retry_get1:
if (rc) {
if (DB_LOCK_DEADLOCK == rc) {
/* try again */
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "entryrdn_get_parent: retry cursor get deadlock\n");
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
goto retry_get1;
} else if (DB_NOTFOUND != rc) {
_entryrdn_cursor_print_error("entryrdn_get_parent",
@@ -1434,6 +1515,9 @@ bail:
"entryrdn_get_parent: Failed to close cursor: %s(%d)\n",
dblayer_strerror(myrc), myrc);
if (DB_LOCK_DEADLOCK == myrc) {
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
ENTRYRDN_DELAY;
continue;
}
@@ -1705,7 +1789,12 @@ retry_get:
*elem = (rdn_elem *)data->data;
if (rc) {
if (DB_LOCK_DEADLOCK == rc) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_get_elem: cursor get deadlock\n");
/* try again */
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
goto retry_get;
} else if (DB_BUFFER_SMALL == rc) {
/* try again */
@@ -1774,6 +1863,11 @@ retry_get0:
rc = cursor->c_get(cursor, key, &data, DB_SET|DB_MULTIPLE);
if (DB_LOCK_DEADLOCK == rc) {
/* try again */
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_get_tombstone_elem: cursor get deadlock\n");
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
goto retry_get0;
} else if (DB_NOTFOUND == rc) {
rc = 0; /* Child not found is ok */
@@ -1824,6 +1918,11 @@ retry_get1:
rc = cursor->c_get(cursor, key, &data, DB_NEXT_DUP|DB_MULTIPLE);
if (DB_LOCK_DEADLOCK == rc) {
/* try again */
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_get_tombstone_elem: retry cursor get deadlock\n");
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
goto retry_get1;
} else if (DB_NOTFOUND == rc) {
rc = 0;
@@ -1842,7 +1941,7 @@ bail:
}
static int
-_entryrdn_put_data(DBC *cursor, DBT *key, DBT *data, char type)
+_entryrdn_put_data(DBC *cursor, DBT *key, DBT *data, char type, DB_TXN *db_txn)
{
int rc = -1;
int db_retry = 0;
@@ -1866,6 +1965,8 @@ _entryrdn_put_data(DBC *cursor, DBT *key, DBT *data, char type)
"_entryrdn_put_data: The same key (%s) and the "
"data exists in index\n",
(char *)key->data);
+ rc = 0;
+ break;
} else {
char *keyword = NULL;
if (type == RDN_INDEX_CHILD) {
@@ -1879,7 +1980,7 @@ _entryrdn_put_data(DBC *cursor, DBT *key, DBT *data, char type)
"_entryrdn_put_data: Adding the %s link (%s) "
"failed: %s (%d)\n", keyword, (char *)key->data,
dblayer_strerror(rc), rc);
- if (DB_LOCK_DEADLOCK == rc) {
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
@@ -1889,13 +1990,19 @@ _entryrdn_put_data(DBC *cursor, DBT *key, DBT *data, char type)
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "_entryrdn_put_data: cursor put operation failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ }
bail:
slapi_log_error(SLAPI_LOG_TRACE, ENTRYRDN_TAG, "<-- _entryrdn_put_data\n");
return rc;
}
static int
-_entryrdn_del_data(DBC *cursor, DBT *key, DBT *data)
+_entryrdn_del_data(DBC *cursor, DBT *key, DBT *data, DB_TXN *db_txn)
{
int rc = -1;
int db_retry = 0;
@@ -1909,37 +2016,57 @@ _entryrdn_del_data(DBC *cursor, DBT *key, DBT *data)
NULL==data?"data":"unknown");
goto bail;
}
-retry_get:
- rc = cursor->c_get(cursor, key, data, DB_GET_BOTH);
- if (rc) {
- if (DB_LOCK_DEADLOCK == rc) {
- /* try again */
- goto retry_get;
- } else if (DB_NOTFOUND == rc) {
- rc = 0; /* not found is ok */
- } else {
- _entryrdn_cursor_print_error("_entryrdn_del_data",
- key->data, data->size, data->ulen, rc);
- }
- } else {
- /* We found it, so delete it */
- for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
- rc = cursor->c_del(cursor, 0);
- if (rc) {
+
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = cursor->c_get(cursor, key, data, DB_GET_BOTH);
+ if (rc) {
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
- "_entryrdn_del_data: Deleting %s failed; "
- "%s(%d)\n", (char *)key->data,
- dblayer_strerror(rc), rc);
- if (DB_LOCK_DEADLOCK == rc) {
- ENTRYRDN_DELAY;
- continue;
- }
+ "_entryrdn_del_data: cursor get deadlock\n");
+ /* try again */
+ } else if (DB_NOTFOUND == rc) {
+ rc = 0; /* not found is ok */
goto bail;
} else {
- break; /* success */
+ _entryrdn_cursor_print_error("_entryrdn_del_data",
+ key->data, data->size, data->ulen, rc);
+ goto bail;
+ }
+ } else {
+ break; /* found it */
+ }
+ }
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "_entryrdn_del_data: cursor get failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ goto bail;
+ }
+
+ /* We found it, so delete it */
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = cursor->c_del(cursor, 0);
+ if (rc) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_del_data: Deleting %s failed; "
+ "%s(%d)\n", (char *)key->data,
+ dblayer_strerror(rc), rc);
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
+ ENTRYRDN_DELAY;
+ continue;
}
+ goto bail;
+ } else {
+ break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "_entryrdn_del_data: cursor del failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ }
bail:
slapi_log_error(SLAPI_LOG_TRACE, ENTRYRDN_TAG,
"<-- _entryrdn_del_data\n");
@@ -1985,7 +2112,7 @@ _entryrdn_insert_key_elems(backend *be,
adddata.flags = DB_DBT_USERMEM;
/* adding RDN to the child key */
- rc = _entryrdn_put_data(cursor, key, &adddata, RDN_INDEX_CHILD);
+ rc = _entryrdn_put_data(cursor, key, &adddata, RDN_INDEX_CHILD, db_txn);
keybuf = key->data;
if (rc) { /* failed */
goto bail;
@@ -2002,7 +2129,7 @@ _entryrdn_insert_key_elems(backend *be,
key->size = key->ulen = strlen(keybuf) + 1;
key->flags = DB_DBT_USERMEM;
- rc = _entryrdn_put_data(cursor, key, &adddata, RDN_INDEX_SELF);
+ rc = _entryrdn_put_data(cursor, key, &adddata, RDN_INDEX_SELF, db_txn);
if (rc) { /* failed */
goto bail;
}
@@ -2022,7 +2149,7 @@ _entryrdn_insert_key_elems(backend *be,
adddata.data = (void *)parentelem;
adddata.flags = DB_DBT_USERMEM;
/* adding RDN to the self key */
- rc = _entryrdn_put_data(cursor, key, &adddata, RDN_INDEX_PARENT);
+ rc = _entryrdn_put_data(cursor, key, &adddata, RDN_INDEX_PARENT, db_txn);
/* Succeeded or failed, it's done. */
bail:
slapi_ch_free_string(&keybuf);
@@ -2036,7 +2163,7 @@ bail:
*/
static int
_entryrdn_replace_suffix_id(DBC *cursor, DBT *key, DBT *adddata,
- ID id, const char *normsuffix)
+ ID id, const char *normsuffix, DB_TXN *db_txn)
{
int rc = 0;
char *keybuf = NULL;
@@ -2061,7 +2188,7 @@ _entryrdn_replace_suffix_id(DBC *cursor, DBT *key, DBT *adddata,
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"_entryrdn_replace_suffix_id: Adding suffix %s failed: "
"%s (%d)\n", normsuffix, dblayer_strerror(rc), rc);
- if (DB_LOCK_DEADLOCK == rc) {
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
@@ -2070,6 +2197,13 @@ _entryrdn_replace_suffix_id(DBC *cursor, DBT *key, DBT *adddata,
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "_entryrdn_replace_suffix_id: cursor put failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ goto bail;
+ }
/*
* Fixing Child link:
@@ -2095,18 +2229,27 @@ _entryrdn_replace_suffix_id(DBC *cursor, DBT *key, DBT *adddata,
memset(&moddata, 0, sizeof(moddata));
moddata.flags = DB_DBT_USERMEM;
-retry_get0:
- rc = cursor->c_get(cursor, key, &data, DB_SET|DB_MULTIPLE);
- if (DB_LOCK_DEADLOCK == rc) {
- /* try again */
- goto retry_get0;
- } else if (DB_NOTFOUND == rc) {
- _entryrdn_cursor_print_error("_entryrdn_replace_suffix_id",
- key->data, data.size, data.ulen, rc);
- goto bail;
- } else if (rc) {
- _entryrdn_cursor_print_error("_entryrdn_replace_suffix_id",
- key->data, data.size, data.ulen, rc);
+
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = cursor->c_get(cursor, key, &data, DB_SET|DB_MULTIPLE);
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_replace_suffix_id: cursor get deadlock\n");
+ /* try again */
+ ENTRYRDN_DELAY;
+ } else if (rc) {
+ _entryrdn_cursor_print_error("_entryrdn_replace_suffix_id",
+ key->data, data.size, data.ulen, rc);
+ goto bail;
+ } else {
+ break; /* found */
+ }
+ }
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "_entryrdn_replace_suffix_id: cursor get1 failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
goto bail;
}
childelems = (rdn_elem **)slapi_ch_calloc(childnum, sizeof(rdn_elem *));
@@ -2124,13 +2267,16 @@ retry_get0:
moddata.data = childelem;
moddata.ulen = moddata.size = _entryrdn_rdn_elem_size(childelem);
/* Delete it first */
- rc = _entryrdn_del_data(cursor, key, &moddata);
+ rc = _entryrdn_del_data(cursor, key, &moddata, db_txn);
if (rc) {
goto bail0;
}
/* Add it back */
rc = _entryrdn_put_data(cursor, &realkey, &moddata,
- RDN_INDEX_CHILD);
+ RDN_INDEX_CHILD, db_txn);
+ if (rc) {
+ goto bail0;
+ }
if (curr_childnum + 1 == childnum) {
childnum *= 2;
childelems = (rdn_elem **)slapi_ch_realloc((char *)childelems,
@@ -2142,19 +2288,33 @@ retry_get0:
/* We don't access the address with this variable any more */
childelem = NULL;
} while (NULL != dataret.data && NULL != ptr);
-retry_get1:
- rc = cursor->c_get(cursor, key, &data, DB_NEXT_DUP|DB_MULTIPLE);
- if (DB_LOCK_DEADLOCK == rc) {
- /* try again */
- goto retry_get1;
- } else if (DB_NOTFOUND == rc) {
- rc = 0;
- break; /* done */
- } else if (rc) {
- _entryrdn_cursor_print_error("_entryrdn_replace_suffix_id",
- key->data, data.size, data.ulen, rc);
+
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = cursor->c_get(cursor, key, &data, DB_NEXT_DUP|DB_MULTIPLE);
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_replace_suffix_id: retry cursor get deadlock\n");
+ /* try again */
+ ENTRYRDN_DELAY;
+ } else if (!rc || (DB_NOTFOUND == rc)) {
+ break; /* done */
+ } else {
+ _entryrdn_cursor_print_error("_entryrdn_replace_suffix_id",
+ key->data, data.size, data.ulen, rc);
+ goto bail0;
+ }
+ }
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "_entryrdn_replace_suffix_id: cursor get2 failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
goto bail0;
}
+ if (DB_NOTFOUND == rc) {
+ rc = 0; /* ok */
+ break; /* we're done */
+ }
} while (0 == rc);
/*
@@ -2176,18 +2336,29 @@ retry_get1:
moddata.flags = DB_DBT_MALLOC;
/* Position cursor at the matching key */
-retry_get2:
- rc = cursor->c_get(cursor, key, &moddata, DB_SET);
- if (rc) {
- if (DB_LOCK_DEADLOCK == rc) {
- /* try again */
- goto retry_get2;
- } else if (rc) {
- _entryrdn_cursor_print_error("_entryrdn_replace_suffix_id",
- key->data, data.size, data.ulen, rc);
- goto bail0;
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = cursor->c_get(cursor, key, &moddata, DB_SET);
+ if (rc) {
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_replace_suffix_id: retry2 cursor get deadlock\n");
+ ENTRYRDN_DELAY;
+ } else {
+ _entryrdn_cursor_print_error("_entryrdn_replace_suffix_id",
+ key->data, data.size, data.ulen, rc);
+ goto bail0;
+ }
+ } else {
+ break;
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "_entryrdn_replace_suffix_id: cursor get3 failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ goto bail0;
+ }
pelem = (rdn_elem *)moddata.data;
if (TMPID == id_stored_to_internal(pelem->rdn_elem_id)) {
/* the parent id is TMPID;
@@ -2200,7 +2371,7 @@ retry_get2:
"_entryrdn_replace_suffix_id: "
"Fixing the parent link (%s) failed: %s (%d)\n",
keybuf, dblayer_strerror(rc), rc);
- if (DB_LOCK_DEADLOCK == rc) {
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
@@ -2209,6 +2380,13 @@ retry_get2:
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "_entryrdn_replace_suffix_id: cursor put failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ goto bail0;
+ }
}
slapi_ch_free((void **)&moddata.data);
} /* for (cep = childelems; cep && *cep; cep++) */
@@ -2220,6 +2398,9 @@ bail0:
bail:
slapi_ch_free_string(&keybuf);
slapi_ch_free_string(&realkeybuf);
+ if (moddata.data && (moddata.flags == DB_DBT_MALLOC)) {
+ slapi_ch_free((void **)&moddata.data);
+ }
return rc;
}
@@ -2294,7 +2475,7 @@ _entryrdn_insert_key(backend *be,
adddata.data = (void *)elem;
adddata.flags = DB_DBT_USERMEM;
- rc = _entryrdn_put_data(cursor, &key, &adddata, RDN_INDEX_SELF);
+ rc = _entryrdn_put_data(cursor, &key, &adddata, RDN_INDEX_SELF, db_txn);
if (DB_KEYEXIST == rc) {
DBT existdata;
rdn_elem *existelem = NULL;
@@ -2308,7 +2489,7 @@ _entryrdn_insert_key(backend *be,
"_entryrdn_insert_key: Get existing suffix %s "
"failed: %s (%d)\n",
nrdn, dblayer_strerror(rc), rc);
- if (DB_LOCK_DEADLOCK == rc) {
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
@@ -2317,12 +2498,19 @@ _entryrdn_insert_key(backend *be,
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_insert_key: cursor get failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ goto bail;
+ }
existelem = (rdn_elem *)existdata.data;
tmpid = id_stored_to_internal(existelem->rdn_elem_id);
slapi_ch_free((void **)&existelem);
if (TMPID == tmpid) {
rc = _entryrdn_replace_suffix_id(cursor, &key, &adddata,
- id, nrdn);
+ id, nrdn, db_txn);
if (rc) {
goto bail;
}
@@ -2401,10 +2589,13 @@ _entryrdn_insert_key(backend *be,
adddata.data = (void *)elem;
adddata.flags = DB_DBT_USERMEM;
- rc = _entryrdn_put_data(cursor, &key, &adddata, RDN_INDEX_SELF);
+ rc = _entryrdn_put_data(cursor, &key, &adddata, RDN_INDEX_SELF, db_txn);
slapi_log_error(SLAPI_LOG_BACKLDBM, ENTRYRDN_TAG,
"_entryrdn_insert_key: Suffix %s added: %d\n",
slapi_rdn_get_rdn(tmpsrdn), rc);
+#ifdef FIX_TXN_DEADLOCKS
+#error no checking for rc here? - what if rc is deadlock? should bail?
+#endif
} else {
slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"_entryrdn_insert_key: Suffix \"%s\" not found: "
@@ -2651,25 +2842,41 @@ _entryrdn_delete_key(backend *be,
memset(&data, 0, sizeof(data));
data.flags = DB_DBT_MALLOC;
-retry_get0:
- rc = cursor->c_get(cursor, &key, &data, DB_SET);
- if (rc) {
- if (DB_LOCK_DEADLOCK == rc) {
- /* try again */
- goto retry_get0;
- } else if (DB_NOTFOUND != rc) {
- _entryrdn_cursor_print_error("_entryrdn_delete_key",
- key.data, data.size, data.ulen, rc);
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = cursor->c_get(cursor, &key, &data, DB_SET);
+ if (rc) {
+ if (DB_LOCK_DEADLOCK == rc) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_delete_key: cursor get deadlock\n");
+ /* try again */
+ if (db_txn) {
+ goto bail; /* have to abort/retry the entire transaction */
+ } else {
+ ENTRYRDN_DELAY; /* sleep for a bit then retry immediately */
+ }
+ } else if (DB_NOTFOUND != rc) {
+ _entryrdn_cursor_print_error("_entryrdn_delete_key",
+ key.data, data.size, data.ulen, rc);
+ goto bail;
+ } else {
+ break; /* DB_NOTFOUND - ok */
+ }
+ } else {
+ slapi_ch_free(&data.data);
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "_entryrdn_delete_key: Failed to remove %s; "
+ "has children\n", nrdn);
+ rc = -1;
goto bail;
}
- } else {
- slapi_ch_free(&data.data);
+ }
+ if (RETRY_TIMES == db_retry) {
slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
- "_entryrdn_delete_key: Failed to remove %s; "
- "has children\n", nrdn);
- rc = -1;
+ "_entryrdn_delete_key: failed after [%d] iterations\n", db_retry);
+ rc = DB_LOCK_DEADLOCK;
goto bail;
}
+
workid = id;
do {
@@ -2777,15 +2984,22 @@ retry_get0:
"_entryrdn_delete_key: Deleting %s failed; "
"%s(%d)\n", (char *)key.data,
dblayer_strerror(rc), rc);
- if (DB_LOCK_DEADLOCK == rc) {
- ENTRYRDN_DELAY;
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
+ ENTRYRDN_DELAY; /* sleep for a bit then retry immediately */
continue;
}
- goto bail;
+ goto bail; /* if deadlock and txn, have to abort entire txn */
} else {
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "_entryrdn_delete_key: delete parent link failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ goto bail;
+ }
} else if (parentnrdn) {
#ifdef LDAP_DEBUG_ENTRYRDN
_entryrdn_dump_rdn_elem(elem);
@@ -2800,15 +3014,22 @@ retry_get0:
"_entryrdn_delete_key: Deleting %s failed; "
"%s(%d)\n", (char *)key.data,
dblayer_strerror(rc), rc);
- if (DB_LOCK_DEADLOCK == rc) {
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
- goto bail;
+ goto bail; /* if deadlock and txn, have to abort entire txn */
} else {
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "_entryrdn_delete_key: delete parent's child link failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ goto bail;
+ }
selfnrdn = nrdn;
workid = id;
} else if (selfnrdn) {
@@ -2824,20 +3045,27 @@ retry_get0:
"_entryrdn_delete_key: Deleting %s failed; "
"%s(%d)\n", (char *)key.data,
dblayer_strerror(rc), rc);
- if (DB_LOCK_DEADLOCK == rc) {
+ if ((DB_LOCK_DEADLOCK == rc) && !db_txn) {
ENTRYRDN_DELAY;
continue;
}
- goto bail;
+ goto bail; /* if deadlock and txn, have to abort entire txn */
} else {
break; /* success */
}
}
+ if (RETRY_TIMES == db_retry) {
+ slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ "_entryrdn_delete_key: delete self link failed after [%d] retries\n",
+ db_retry);
+ rc = DB_LOCK_DEADLOCK;
+ }
goto bail; /* done */
}
} while (workid);
bail:
+ slapi_ch_free_string(&parentnrdn);
slapi_ch_free_string(&keybuf);
slapi_ch_free((void **)&elem);
slapi_log_error(SLAPI_LOG_TRACE, ENTRYRDN_TAG,
@@ -3107,6 +3335,11 @@ _entryrdn_index_read(backend *be,
retry_get0:
rc = cursor->c_get(cursor, &key, &data, DB_SET|DB_MULTIPLE);
if (DB_LOCK_DEADLOCK == rc) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_index_read: cursor get deadlock\n");
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
/* try again */
goto retry_get0;
} else if (DB_NOTFOUND == rc) {
@@ -3146,6 +3379,11 @@ retry_get0:
retry_get1:
rc = cursor->c_get(cursor, &key, &data, DB_NEXT_DUP|DB_MULTIPLE);
if (DB_LOCK_DEADLOCK == rc) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_index_read: retry cursor get deadlock\n");
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
/* try again */
goto retry_get1;
} else if (DB_NOTFOUND == rc) {
@@ -3197,7 +3435,12 @@ retry_get0:
rc = cursor->c_get(cursor, &key, &data, DB_SET|DB_MULTIPLE);
if (rc) {
if (DB_LOCK_DEADLOCK == rc) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_append_childidl: cursor get deadlock\n");
/* try again */
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
goto retry_get0;
} else if (DB_NOTFOUND == rc) {
rc = 0; /* okay not to have children */
@@ -3242,7 +3485,12 @@ retry_get1:
rc = cursor->c_get(cursor, &key, &data, DB_NEXT_DUP|DB_MULTIPLE);
if (rc) {
if (DB_LOCK_DEADLOCK == rc) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_append_childidl: retry cursor get deadlock\n");
/* try again */
+#ifdef FIX_TXN_DEADLOCKS
+#error if txn != NULL, have to retry the entire transaction
+#endif
goto retry_get1;
} else if (DB_NOTFOUND == rc) {
rc = 0; /* okay not to have children */
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
index bdc2967..f7520c6 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
@@ -460,25 +460,17 @@ ldbm_back_modify( Slapi_PBlock *pb )
/* New entry 'ec' is in the entry cache.
* Remove it from the cache once. */
CACHE_REMOVE(&inst->inst_cache, ec);
- cache_unlock_entry(&inst->inst_cache, e);
- CACHE_RETURN(&inst->inst_cache, ec);
+ CACHE_RETURN(&inst->inst_cache, &ec);
} else {
backentry_free(&ec);
}
+ ec_in_cache = 0; /* added to cache by id2entry - have to remove to try again */
slapi_pblock_set( pb, SLAPI_MODIFY_EXISTING_ENTRY, original_entry->ep_entry );
ec = original_entry;
if ( (original_entry = backentry_dup( e )) == NULL ) {
ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
}
- /* Put new entry 'ec' into the entry cache. */
- if (ec_in_cache && CACHE_ADD(&inst->inst_cache, ec, NULL) < 0) {
- LDAPDebug1Arg(LDAP_DEBUG_ANY,
- "ldbm_back_modify: adding %s to cache failed\n",
- slapi_entry_get_dn_const(ec->ep_entry));
- ldap_result_code = LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
LDAPDebug0Args(LDAP_DEBUG_BACKLDBM,
"Modify Retrying Transaction\n");
#ifndef LDBM_NO_BACKOFF_DELAY
@@ -603,7 +595,7 @@ ldbm_back_modify( Slapi_PBlock *pb )
}
if (retry_count == RETRY_TIMES) {
LDAPDebug( LDAP_DEBUG_ANY, "Retry count exceeded in modify\n", 0, 0, 0 );
- ldap_result_code= LDAP_OPERATIONS_ERROR;
+ ldap_result_code= LDAP_BUSY;
goto error_return;
}
@@ -629,6 +621,7 @@ ldbm_back_modify( Slapi_PBlock *pb )
ec->ep_entry->e_virtual_watermark = 0;
/* we must return both e (which has been deleted) and new entry ec */
+ /* cache_replace removes e from the caches */
cache_unlock_entry( &inst->inst_cache, e );
CACHE_RETURN( &inst->inst_cache, &e );
/*
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
index b3d8111..c7d821a 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
@@ -46,11 +46,11 @@
#include "back-ldbm.h"
static const char *moddn_get_newdn(Slapi_PBlock *pb, Slapi_DN *dn_olddn, Slapi_DN *dn_newrdn, Slapi_DN *dn_newsuperiordn);
-static void moddn_unlock_and_return_entries(backend *be,struct backentry **targetentry, struct backentry **existingentry);
+static void moddn_unlock_and_return_entry(backend *be,struct backentry **targetentry);
static int moddn_newrdn_mods(Slapi_PBlock *pb, const char *olddn, struct backentry *ec, Slapi_Mods *smods_wsi, int is_repl_op);
static IDList *moddn_get_children(back_txn *ptxn, Slapi_PBlock *pb, backend *be, struct backentry *parententry, Slapi_DN *parentdn, struct backentry ***child_entries, struct backdn ***child_dns);
static int moddn_rename_children(back_txn *ptxn, Slapi_PBlock *pb, backend *be, IDList *children, Slapi_DN *dn_parentdn, Slapi_DN *dn_newsuperiordn, struct backentry *child_entries[]);
-static int modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbminfo *li, struct backentry *e, struct backentry *ec, Slapi_Mods *smods1, Slapi_Mods *smods2, Slapi_Mods *smods3);
+static int modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbminfo *li, struct backentry *e, struct backentry **ec, Slapi_Mods *smods1, Slapi_Mods *smods2, Slapi_Mods *smods3, int *e_in_cache, int *ec_in_cache);
static void mods_remove_nsuniqueid(Slapi_Mods *smods);
#define MOD_SET_ERROR(rc, error, count) \
@@ -68,6 +68,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
struct backentry *e= NULL;
struct backentry *ec= NULL;
int ec_in_cache= 0;
+ int e_in_cache= 0;
back_txn txn;
back_txnid parent_txn;
int retval = -1;
@@ -81,7 +82,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
char *ldap_result_matcheddn= NULL;
struct backentry *parententry= NULL;
struct backentry *newparententry= NULL;
- struct backentry *existingentry= NULL;
struct backentry *original_entry = NULL;
struct backentry *original_parent = NULL;
struct backentry *original_newparent = NULL;
@@ -120,6 +120,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
const char *newdn = NULL;
char *newrdn = NULL;
int opreturn = 0;
+ int free_modrdn_existing_entry = 0;
/* sdn & parentsdn need to be initialized before "goto *_return" */
slapi_sdn_init(&dn_newdn);
@@ -254,6 +255,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
{
goto error_return;
}
+ free_modrdn_existing_entry = 1; /* need to free it */
}
/* <old superior> */
@@ -349,6 +351,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
ldap_result_code= -1;
goto error_return; /* error result sent by find_entry2modify() */
}
+ e_in_cache = 1; /* e is in the cache and locked */
/* Check that an entry with the same DN doesn't already exist. */
{
Slapi_Entry *entry;
@@ -518,17 +521,21 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
}
/* create it in the cache - prevents others from creating it */
- if (( cache_add_tentative( &inst->inst_cache, ec, NULL ) != 0 ) &&
+ if (( cache_add_tentative( &inst->inst_cache, ec, NULL ) != 0 ) ) {
+ ec_in_cache = 0; /* not in cache */
/* allow modrdn even if the src dn and dest dn are identical */
- ( 0 != slapi_sdn_compare((const Slapi_DN *)&dn_newdn,
- (const Slapi_DN *)sdn)) )
- {
- /* somebody must've created it between dn2entry() and here */
- /* JCMREPL - Hmm... we can't permit this to happen...? */
- ldap_result_code= LDAP_ALREADY_EXISTS;
- goto error_return;
+ if ( 0 != slapi_sdn_compare((const Slapi_DN *)&dn_newdn,
+ (const Slapi_DN *)sdn) ) {
+ /* somebody must've created it between dn2entry() and here */
+ /* JCMREPL - Hmm... we can't permit this to happen...? */
+ ldap_result_code= LDAP_ALREADY_EXISTS;
+ goto error_return;
+ }
+ /* so if the old dn is the same as the new dn, the entry will not be cached
+ until it is replaced with cache_replace */
+ } else {
+ ec_in_cache = 1;
}
- ec_in_cache= 1;
/* Build the list of modifications required to the existing entry */
{
@@ -725,15 +732,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
}
- if ( (original_parent = backentry_dup( parententry )) == NULL ) {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
- if ( newparententry &&
- ((original_newparent = backentry_dup( newparententry )) == NULL) ) {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
slapi_pblock_get(pb, SLAPI_MODRDN_TARGET_ENTRY, &target_entry);
if ( (original_targetentry = slapi_entry_dup(target_entry)) == NULL ) {
ldap_result_code= LDAP_OPERATIONS_ERROR;
@@ -754,6 +752,8 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
{
if (txn.back_txn_txn && (txn.back_txn_txn != parent_txn))
{
+ Slapi_Entry *ent = NULL;
+
dblayer_txn_abort(li,&txn);
/* txn is no longer valid - reset slapi_txn to the parent */
slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
@@ -761,6 +761,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn);
slapi_ch_free_string(&newrdn);
slapi_pblock_set(pb, SLAPI_MODRDN_NEWRDN, original_newrdn);
+ slapi_sdn_set_normdn_byref(&dn_newrdn, original_newrdn);
original_newrdn = slapi_ch_strdup(original_newrdn);
slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &dn_newsuperiordn);
@@ -769,27 +770,51 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
orig_dn_newsuperiordn = slapi_sdn_dup(orig_dn_newsuperiordn);
if (ec_in_cache) {
/* New entry 'ec' is in the entry cache.
- * Remove it from teh cache once. */
+ * Remove it from the cache . */
CACHE_REMOVE(&inst->inst_cache, ec);
- cache_unlock_entry(&inst->inst_cache, e);
- CACHE_RETURN(&inst->inst_cache, ec);
+ CACHE_RETURN(&inst->inst_cache, &ec);
+#ifdef DEBUG_CACHE
+ PR_ASSERT(ec == NULL);
+#endif
+ ec_in_cache = 0;
} else {
backentry_free(&ec);
}
- slapi_pblock_set( pb, SLAPI_MODRDN_EXISTING_ENTRY, original_entry->ep_entry );
+ /* make sure the original entry is back in the cache if it was removed */
+ if (!e_in_cache) {
+ CACHE_ADD(&inst->inst_cache, e, NULL);
+ e_in_cache = 1;
+ }
+ slapi_pblock_get( pb, SLAPI_MODRDN_EXISTING_ENTRY, &ent );
+ if (ent && (ent != original_entry->ep_entry)) {
+ slapi_entry_free(ent);
+ slapi_pblock_set( pb, SLAPI_MODRDN_EXISTING_ENTRY, NULL );
+ }
ec = original_entry;
if ( (original_entry = backentry_dup( ec )) == NULL ) {
ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
}
- if (ec_in_cache &&
+ slapi_pblock_set( pb, SLAPI_MODRDN_EXISTING_ENTRY, original_entry->ep_entry );
+ free_modrdn_existing_entry = 0; /* owned by original_entry now */
+ if (!ec_in_cache) {
/* Put the resetted entry 'ec' into the cache again. */
- (cache_add_tentative( &inst->inst_cache, ec, NULL ) != 0)) {
- LDAPDebug1Arg(LDAP_DEBUG_ANY,
- "ldbm_back_modrdn: adding %s to cache failed\n",
- slapi_entry_get_dn_const(ec->ep_entry));
- ldap_result_code = LDAP_OPERATIONS_ERROR;
- goto error_return;
+ if (cache_add_tentative( &inst->inst_cache, ec, NULL ) != 0) {
+ ec_in_cache = 0; /* not in cache */
+ /* allow modrdn even if the src dn and dest dn are identical */
+ if ( 0 != slapi_sdn_compare((const Slapi_DN *)&dn_newdn,
+ (const Slapi_DN *)sdn) ) {
+ LDAPDebug1Arg(LDAP_DEBUG_ANY,
+ "ldbm_back_modrdn: adding %s to cache failed\n",
+ slapi_entry_get_dn_const(ec->ep_entry));
+ ldap_result_code = LDAP_OPERATIONS_ERROR;
+ goto error_return;
+ }
+ /* so if the old dn is the same as the new dn, the entry will not be cached
+ until it is replaced with cache_replace */
+ } else {
+ ec_in_cache = 1;
+ }
}
slapi_pblock_get(pb, SLAPI_MODRDN_TARGET_ENTRY, &target_entry );
@@ -800,28 +825,16 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
goto error_return;
}
- backentry_free(&parententry);
- slapi_pblock_set( pb, SLAPI_MODRDN_PARENT_ENTRY, original_parent->ep_entry );
- parententry = original_parent;
- if ( (original_entry = backentry_dup( parententry )) == NULL ) {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
-
- backentry_free(&newparententry);
- if (original_newparent) {
- slapi_pblock_set( pb, SLAPI_MODRDN_NEWPARENT_ENTRY,
- original_newparent->ep_entry );
- }
- newparententry = original_entry;
- if ( newparententry &&
- ((original_entry = backentry_dup(newparententry)) == NULL) ) {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
/* We're re-trying */
LDAPDebug0Args(LDAP_DEBUG_BACKLDBM,
"Modrdn Retrying Transaction\n");
+#ifndef LDBM_NO_BACKOFF_DELAY
+ {
+ PRIntervalTime interval;
+ interval = PR_MillisecondsToInterval(slapi_rand() % 100);
+ DS_Sleep(interval);
+ }
+#endif
}
retval = dblayer_txn_begin(li,parent_txn,&txn);
if (0 != retval) {
@@ -852,7 +865,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
/*
* Update the indexes for the entry.
*/
- retval = modrdn_rename_entry_update_indexes(&txn, pb, li, e, ec, &smods_generated, &smods_generated_wsi, &smods_operation_wsi);
+ retval = modrdn_rename_entry_update_indexes(&txn, pb, li, e, &ec, &smods_generated, &smods_generated_wsi, &smods_operation_wsi, &e_in_cache, &ec_in_cache);
if (DB_LOCK_DEADLOCK == retval)
{
/* Retry txn */
@@ -979,11 +992,14 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
{
Slapi_RDN newsrdn;
slapi_rdn_init_sdn(&newsrdn, (const Slapi_DN *)&dn_newdn);
- rc = entryrdn_rename_subtree(be, (const Slapi_DN *)sdn, &newsrdn,
- (const Slapi_DN *)dn_newsuperiordn,
- e->ep_id, &txn);
+ retval = entryrdn_rename_subtree(be, (const Slapi_DN *)sdn, &newsrdn,
+ (const Slapi_DN *)dn_newsuperiordn,
+ e->ep_id, &txn);
slapi_rdn_done(&newsrdn);
- if (rc) {
+ if (retval != 0) {
+ if (retval == DB_LOCK_DEADLOCK) continue;
+ if (retval == DB_RUNRECOVERY || LDBM_OS_ERR_IS_DISKFULL(retval))
+ disk_full = 1;
MOD_SET_ERROR(ldap_result_code,
LDAP_OPERATIONS_ERROR, retry_count);
goto error_return;
@@ -1035,7 +1051,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
{
/* Failed */
LDAPDebug( LDAP_DEBUG_ANY, "Retry count exceeded in modrdn\n", 0, 0, 0 );
- ldap_result_code= LDAP_OPERATIONS_ERROR;
+ ldap_result_code= LDAP_BUSY;
goto error_return;
}
@@ -1128,12 +1144,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
}
retval= 0;
-#if 0 /* this new entry in the cache can be used for future; don't remove it */
- /* remove from cache so that memory can be freed by cache_return */
- if (ec_in_cache) {
- CACHE_REMOVE(&inst->inst_cache, ec);
- }
-#endif
goto common_return;
error_return:
@@ -1151,13 +1161,6 @@ error_return:
CACHE_REMOVE(&inst->inst_dncache, bdn);
CACHE_RETURN(&inst->inst_dncache, &bdn);
}
- if( ec!=NULL ) {
- if (ec_in_cache) {
- CACHE_REMOVE(&inst->inst_cache, ec);
- } else {
- backentry_free( &ec );
- }
- }
if(children)
{
int i = 0;
@@ -1245,13 +1248,6 @@ error_return:
common_return:
- /* Free up the resource we don't need any more */
- if(ec_in_cache) {
- CACHE_RETURN( &inst->inst_cache, &ec );
- }
-
- moddn_unlock_and_return_entries(be,&e,&existingentry);
-
/* result code could be used in the bepost plugin functions. */
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
/*
@@ -1259,6 +1255,32 @@ common_return:
*/
plugin_call_plugins (pb, SLAPI_PLUGIN_BE_POST_MODRDN_FN);
+ /* Free up the resource we don't need any more */
+ if (ec) {
+ /* remove the new entry from the cache if the op failed -
+ otherwise, leave it in */
+ if (ec_in_cache && retval) {
+ CACHE_REMOVE( &inst->inst_cache, ec );
+ }
+ if (ec_in_cache) {
+ CACHE_RETURN( &inst->inst_cache, &ec );
+ } else {
+ backentry_free( &ec );
+ }
+ ec = NULL;
+ ec_in_cache = 0;
+ }
+
+ /* put e back in the cache if the modrdn failed */
+ if (e) {
+ if (!e_in_cache && retval) {
+ CACHE_ADD(&inst->inst_cache, e, NULL);
+ e_in_cache = 1;
+ }
+ }
+
+ moddn_unlock_and_return_entry(be,&e);
+
if (ruv_c_init) {
modify_term(&ruv_c, be);
}
@@ -1281,7 +1303,11 @@ common_return:
slapi_sdn_done(&dn_parentdn);
modify_term(&parent_modify_context,be);
modify_term(&newparent_modify_context,be);
- done_with_pblock_entry(pb,SLAPI_MODRDN_EXISTING_ENTRY);
+ if (free_modrdn_existing_entry) {
+ done_with_pblock_entry(pb,SLAPI_MODRDN_EXISTING_ENTRY);
+ } else { /* owned by original_entry */
+ slapi_pblock_set(pb, SLAPI_MODRDN_EXISTING_ENTRY, NULL);
+ }
done_with_pblock_entry(pb,SLAPI_MODRDN_PARENT_ENTRY);
done_with_pblock_entry(pb,SLAPI_MODRDN_NEWPARENT_ENTRY);
done_with_pblock_entry(pb,SLAPI_MODRDN_TARGET_ENTRY);
@@ -1354,10 +1380,9 @@ moddn_get_newdn(Slapi_PBlock *pb, Slapi_DN *dn_olddn, Slapi_DN *dn_newrdn, Slapi
* Return the entries to the cache.
*/
static void
-moddn_unlock_and_return_entries(
+moddn_unlock_and_return_entry(
backend *be,
- struct backentry **targetentry,
- struct backentry **existingentry)
+ struct backentry **targetentry)
{
ldbm_instance *inst = (ldbm_instance *) be->be_instance_info;
@@ -1367,10 +1392,6 @@ moddn_unlock_and_return_entries(
CACHE_RETURN( &inst->inst_cache, targetentry );
*targetentry= NULL;
}
- if ( *existingentry!=NULL ) {
- CACHE_RETURN( &inst->inst_cache, existingentry );
- *existingentry= NULL;
- }
}
@@ -1540,8 +1561,8 @@ moddn_newrdn_mods(Slapi_PBlock *pb, const char *olddn, struct backentry *ec, Sla
}
else
{
- LDAPDebug( LDAP_DEBUG_TRACE, "moddn_newrdn_mods failed: could not parse new rdn %s\n",
- newrdn, 0, 0);
+ LDAPDebug( LDAP_DEBUG_TRACE, "moddn_newrdn_mods failed: could not parse new rdn %s\n",
+ newrdn, 0, 0);
return LDAP_OPERATIONS_ERROR;
}
@@ -1568,7 +1589,7 @@ mods_remove_nsuniqueid(Slapi_Mods *smods)
* mods contains the list of attribute change made.
*/
static int
-modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbminfo *li, struct backentry *e, struct backentry *ec, Slapi_Mods *smods1, Slapi_Mods *smods2, Slapi_Mods *smods3)
+modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbminfo *li, struct backentry *e, struct backentry **ec, Slapi_Mods *smods1, Slapi_Mods *smods2, Slapi_Mods *smods3, int *e_in_cache, int *ec_in_cache)
{
backend *be;
ldbm_instance *inst;
@@ -1576,36 +1597,41 @@ modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbm
char *msg;
Slapi_Operation *operation;
int is_ruv = 0; /* True if the current entry is RUV */
+ int orig_ec_in_cache = 0;
slapi_pblock_get( pb, SLAPI_BACKEND, &be );
slapi_pblock_get( pb, SLAPI_OPERATION, &operation );
is_ruv = operation_is_flag_set(operation, OP_FLAG_REPL_RUV);
inst = (ldbm_instance *) be->be_instance_info;
+ orig_ec_in_cache = *ec_in_cache;
/*
* Update the ID to Entry index.
* Note that id2entry_add replaces the entry, so the Entry ID stays the same.
*/
- retval = id2entry_add( be, ec, ptxn );
+ retval = id2entry_add( be, *ec, ptxn );
if (DB_LOCK_DEADLOCK == retval)
{
/* Retry txn */
+ LDAPDebug0Args( LDAP_DEBUG_BACKLDBM, "modrdn_rename_entry_update_indexes: id2entry_add deadlock\n" );
goto error_return;
}
if (retval != 0)
{
- LDAPDebug( LDAP_DEBUG_ANY, "id2entry_add failed, err=%d %s\n", retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
+ LDAPDebug( LDAP_DEBUG_ANY, "modrdn_rename_entry_update_indexes: id2entry_add failed, err=%d %s\n", retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
goto error_return;
}
+ *ec_in_cache = 1; /* id2entry_add adds to cache if not already in */
if(smods1!=NULL && slapi_mods_get_num_mods(smods1)>0)
{
/*
* update the indexes: lastmod, rdn, etc.
*/
- retval = index_add_mods( be, slapi_mods_get_ldapmods_byref(smods1), e, ec, ptxn );
+ retval = index_add_mods( be, slapi_mods_get_ldapmods_byref(smods1), e, *ec, ptxn );
if (DB_LOCK_DEADLOCK == retval)
{
/* Retry txn */
+ LDAPDebug0Args( LDAP_DEBUG_BACKLDBM, "modrdn_rename_entry_update_indexes: index_add_mods1 deadlock\n" );
goto error_return;
}
if (retval != 0)
@@ -1625,10 +1651,11 @@ modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbm
/*
* update the indexes: lastmod, rdn, etc.
*/
- retval = index_add_mods( be, slapi_mods_get_ldapmods_byref(smods2), e, ec, ptxn );
+ retval = index_add_mods( be, slapi_mods_get_ldapmods_byref(smods2), e, *ec, ptxn );
if (DB_LOCK_DEADLOCK == retval)
{
/* Retry txn */
+ LDAPDebug0Args( LDAP_DEBUG_BACKLDBM, "modrdn_rename_entry_update_indexes: index_add_mods2 deadlock\n" );
goto error_return;
}
if (retval != 0)
@@ -1642,10 +1669,11 @@ modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbm
/*
* update the indexes: lastmod, rdn, etc.
*/
- retval = index_add_mods( be, slapi_mods_get_ldapmods_byref(smods3), e, ec, ptxn );
+ retval = index_add_mods( be, slapi_mods_get_ldapmods_byref(smods3), e, *ec, ptxn );
if (DB_LOCK_DEADLOCK == retval)
{
/* Retry txn */
+ LDAPDebug0Args( LDAP_DEBUG_BACKLDBM, "modrdn_rename_entry_update_indexes: index_add_mods3 deadlock\n" );
goto error_return;
}
if (retval != 0)
@@ -1661,10 +1689,11 @@ modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbm
*/
if (!is_ruv)
{
- retval= vlv_update_all_indexes(ptxn, be, pb, e, ec);
+ retval= vlv_update_all_indexes(ptxn, be, pb, e, *ec);
if (DB_LOCK_DEADLOCK == retval)
{
/* Abort and re-try */
+ LDAPDebug0Args( LDAP_DEBUG_BACKLDBM, "modrdn_rename_entry_update_indexes: vlv_update_all_indexes deadlock\n" );
goto error_return;
}
if (retval != 0)
@@ -1673,9 +1702,18 @@ modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbm
goto error_return;
}
}
- if (cache_replace( &inst->inst_cache, e, ec ) != 0 ) {
+ if (cache_replace( &inst->inst_cache, e, *ec ) != 0 ) {
+ LDAPDebug0Args( LDAP_DEBUG_BACKLDBM, "modrdn_rename_entry_update_indexes cache_replace failed\n");
retval= -1;
goto error_return;
+ } else {
+ *e_in_cache = 0; /* e un-cached */
+ }
+ if (orig_ec_in_cache) {
+ /* ec was already added to the cache via cache_add_tentative (to reserve its spot in the cache)
+ and/or id2entry_add - so it already had one refcount - cache_replace adds another refcount -
+ drop the extra ref added by cache_replace */
+ CACHE_RETURN( &inst->inst_cache, ec );
}
error_return:
return retval;
@@ -1687,7 +1725,7 @@ moddn_rename_child_entry(
Slapi_PBlock *pb,
struct ldbminfo *li,
struct backentry *e,
- struct backentry *ec,
+ struct backentry **ec,
int parentdncomps,
char **newsuperiordns,
int newsuperiordncomps,
@@ -1711,8 +1749,10 @@ moddn_rename_child_entry(
int olddncomps= 0;
int need= 1; /* For the '\0' */
int i;
+ int e_in_cache = 1;
+ int ec_in_cache = 0;
- olddn = slapi_entry_get_dn(ec->ep_entry);
+ olddn = slapi_entry_get_dn((*ec)->ep_entry);
if (NULL == olddn) {
return retval;
}
@@ -1747,9 +1787,9 @@ moddn_rename_child_entry(
}
}
slapi_ldap_value_free( olddns );
- slapi_entry_set_dn( ec->ep_entry, newdn );
+ slapi_entry_set_dn( (*ec)->ep_entry, newdn );
/* add the entrydn operational attributes */
- add_update_entrydn_operational_attributes (ec);
+ add_update_entrydn_operational_attributes (*ec);
/*
* Update the DN CSN of the entry.
@@ -1767,13 +1807,14 @@ moddn_rename_child_entry(
slapi_mods_add( &smods, LDAP_MOD_DELETE, LDBM_ENTRYDN_STR,
strlen( backentry_get_ndn(e) ), backentry_get_ndn(e) );
slapi_mods_add( &smods, LDAP_MOD_REPLACE, LDBM_ENTRYDN_STR,
- strlen( backentry_get_ndn(ec) ), backentry_get_ndn(ec) );
+ strlen( backentry_get_ndn(*ec) ), backentry_get_ndn(*ec) );
smodsp = &smods;
/*
* Update all the indexes.
*/
retval = modrdn_rename_entry_update_indexes(ptxn, pb, li, e, ec,
- smodsp, NULL, NULL);
+ smodsp, NULL, NULL,
+ &e_in_cache, &ec_in_cache);
/* JCMREPL - Should the children get updated modifiersname and lastmodifiedtime? */
slapi_mods_done(&smods);
}
@@ -1850,7 +1891,7 @@ moddn_rename_children(
opcsn = operation_get_csn (operation);
for (i=0,retval=0; retval == 0 && child_entries[i] && child_entry_copies[i]; i++) {
retval = moddn_rename_child_entry(ptxn, pb, li, child_entries[i],
- child_entry_copies[i], parentdncomps,
+ &child_entry_copies[i], parentdncomps,
newsuperiordns, newsuperiordncomps,
opcsn );
}
diff --git a/ldap/servers/slapd/back-ldbm/misc.c b/ldap/servers/slapd/back-ldbm/misc.c
index 8140818..a56069b 100644
--- a/ldap/servers/slapd/back-ldbm/misc.c
+++ b/ldap/servers/slapd/back-ldbm/misc.c
@@ -53,7 +53,7 @@ void ldbm_nasty(const char* str, int c, int err)
char buffer[200];
if (err == DB_LOCK_DEADLOCK) {
PR_snprintf(buffer,200,"%s WARNING %d",str,c);
- LDAPDebug(LDAP_DEBUG_TRACE,"%s, err=%d %s\n",
+ LDAPDebug(LDAP_DEBUG_BACKLDBM,"%s, err=%d %s\n",
buffer,err,(msg = dblayer_strerror( err )) ? msg : "");
} else if (err == DB_RUNRECOVERY) {
LDAPDebug2Args(LDAP_DEBUG_ANY, "FATAL ERROR at %s (%d); "
diff --git a/ldap/servers/slapd/back-ldbm/seq.c b/ldap/servers/slapd/back-ldbm/seq.c
index ac958ad..1435ba2 100644
--- a/ldap/servers/slapd/back-ldbm/seq.c
+++ b/ldap/servers/slapd/back-ldbm/seq.c
@@ -240,6 +240,9 @@ ldbm_back_seq( Slapi_PBlock *pb )
idl = idl_fetch( be, db, &key, NULL, 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;
} else {
break;
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 2e4db56..b896755 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1242,7 +1242,8 @@ enum
BE_STATE_STOPPED = 1, /* backend is initialized but not started */
BE_STATE_STARTED, /* backend is started */
BE_STATE_CLEANED, /* backend was cleaned up */
- BE_STATE_DELETED /* backend is removed */
+ BE_STATE_DELETED, /* backend is removed */
+ BE_STATE_STOPPING /* told to stop but not yet stopped */
};
struct conn;
11 years, 6 months
Branch '389-ds-base-1.2.10' - ldap/servers
by Richard Allen Megginson
ldap/servers/plugins/usn/usn.c | 11 -------
ldap/servers/slapd/back-ldbm/ldbm_delete.c | 42 ++++++-----------------------
2 files changed, 10 insertions(+), 43 deletions(-)
New commits:
commit cc4095d2eca31608afd6c0d04e7c3f45d6a7ae49
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Tue May 22 19:13:47 2012 -0600
Ticket #382 - DS Shuts down intermittently
https://fedorahosted.org/389/ticket/382
Resolves: Ticket #382
Bug Description: DS Shuts down intermittently
Reviewed by: nhosoi (Thanks!)
Branch: 389-ds-base-1.2.10
Fix Description: The usn code called from ldbm_back_delete was adding
entryusn and preventryusn to the entry directly in the cache. If another
thread was accessing the entry (e.g. an internal search done by referint or
memberof, or an external search) at the same time, the server would crash.
The fix is to not modify the cached entry directly - instead, modify a
copy of the entry, and apply the entryusn set in the copy to the tombstone.
Then we don't need to use SLAPI_DELETE_BEPREOP_ENTRY or
SLAPI_DELETE_BEPOSTOP_ENTRY at all. We don't need to clean up the
postentry - we are not setting entryusn or preventryusn in the real entry -
we are setting those values in the tombstone entry - if successful, the
values will be added or deleted accordingly - if not successful, the
values are thrown away and freed.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
diff --git a/ldap/servers/plugins/usn/usn.c b/ldap/servers/plugins/usn/usn.c
index c8672d5..da85f7d 100644
--- a/ldap/servers/plugins/usn/usn.c
+++ b/ldap/servers/plugins/usn/usn.c
@@ -429,7 +429,7 @@ usn_bepreop_delete(Slapi_PBlock *pb)
"--> usn_bepreop_delete\n");
/* add next USN to the entry; "be" contains the usn counter */
- slapi_pblock_get(pb, SLAPI_DELETE_BEPREOP_ENTRY, &e);
+ slapi_pblock_get(pb, SLAPI_DELETE_EXISTING_ENTRY, &e);
if (NULL == e) {
rc = LDAP_NO_SUCH_OBJECT;
goto bail;
@@ -576,15 +576,6 @@ usn_bepostop_delete (Slapi_PBlock *pb)
/* if op is not successful, don't increment the counter */
slapi_pblock_get(pb, SLAPI_RESULT_CODE, &rc);
if (LDAP_SUCCESS != rc) {
- Slapi_Entry *e = NULL;
-
- slapi_pblock_get(pb, SLAPI_DELETE_BEPOSTOP_ENTRY, &e);
- if (NULL == e) {
- rc = LDAP_NO_SUCH_OBJECT;
- goto bail;
- }
- /* okay to return the rc from slapi_entry_delete_values */
- rc = slapi_entry_delete_values(e, SLAPI_ATTR_ENTRYUSN_PREV, NULL);
goto bail;
}
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
index 014af73..865ae2f 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
@@ -94,7 +94,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
int addordel_flags = 0; /* passed to index_addordel */
char *entryusn_str = NULL;
char *prev_entryusn_str = NULL;
- Slapi_Entry *orig_entry = NULL;
Slapi_DN parentsdn;
slapi_pblock_get( pb, SLAPI_BACKEND, &be);
@@ -187,10 +186,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
goto error_return;
}
- /* set entry in case be-preop plugins need to work on it (e.g., USN) */
- slapi_pblock_get( pb, SLAPI_DELETE_BEPREOP_ENTRY, &orig_entry );
- slapi_pblock_set( pb, SLAPI_DELETE_BEPREOP_ENTRY, e->ep_entry );
-
/* Don't call pre-op for Tombstone entries */
if (!delete_tombstone_entry)
{
@@ -205,8 +200,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
if(ldap_result_code==LDAP_OPERATIONS_ERROR ||
ldap_result_code==LDAP_INVALID_DN_SYNTAX)
{
- /* restore original entry so the front-end delete code can free it */
- slapi_pblock_set( pb, SLAPI_DELETE_BEPREOP_ENTRY, orig_entry );
/* retval is -1 */
goto error_return;
}
@@ -221,8 +214,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
* or that this Operation became a No-Op.
*/
slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
- /* restore original entry so the front-end delete code can free it */
- slapi_pblock_set( pb, SLAPI_DELETE_BEPREOP_ENTRY, orig_entry );
/* retval is -1 */
goto error_return;
}
@@ -231,8 +222,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
OP_FLAG_TOMBSTONE_ENTRY);
}
- slapi_pblock_set( pb, SLAPI_DELETE_BEPREOP_ENTRY, orig_entry );
-
/*
* Sanity check to avoid to delete a non-tombstone or to tombstone again
* a tombstone entry. This should not happen (see bug 561003).
@@ -381,6 +370,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
char *tombstone_dn = compute_entry_tombstone_dn(slapi_entry_get_dn(e->ep_entry),
childuniqueid);
Slapi_Value *tomb_value;
+ Slapi_Entry *e_with_usn = NULL;
nscpEntrySDN = slapi_entry_get_sdn(e->ep_entry);
@@ -422,20 +412,16 @@ ldbm_back_delete( Slapi_PBlock *pb )
slapi_entry_add_value(tombstone->ep_entry, SLAPI_ATTR_OBJECTCLASS, tomb_value);
slapi_value_free(&tomb_value);
- /* retrieve previous entry usn value, if any */
- prev_entryusn_str = slapi_entry_attr_get_charptr(tombstone->ep_entry,
- SLAPI_ATTR_ENTRYUSN_PREV);
- if (prev_entryusn_str) {
- /* discard the previous value from the tombstone entry */
- retval = slapi_entry_delete_string(tombstone->ep_entry,
- SLAPI_ATTR_ENTRYUSN_PREV, prev_entryusn_str);
- if (0 != retval) {
- LDAPDebug( LDAP_DEBUG_TRACE,
- "delete (deleting %s) failed, err=%d\n",
- SLAPI_ATTR_ENTRYUSN, retval, 0) ;
+ /* new usn was set in SLAPI_DELETE_EXISTING_ENTRY by usn code */
+ slapi_pblock_get(pb, SLAPI_DELETE_EXISTING_ENTRY, &e_with_usn);
+ if (e_with_usn) {
+ char *new_usn = slapi_entry_attr_get_charptr(e_with_usn, SLAPI_ATTR_ENTRYUSN);
+ if (new_usn) {
+ slapi_entry_attr_set_charptr(tombstone->ep_entry, SLAPI_ATTR_ENTRYUSN, new_usn);
+ slapi_ch_free_string(&new_usn);
}
+ prev_entryusn_str = slapi_entry_attr_get_charptr(e_with_usn, SLAPI_ATTR_ENTRYUSN_PREV);
}
-
/* XXXggood above used to be: slapi_entry_add_string(tombstone->ep_entry, SLAPI_ATTR_OBJECTCLASS, SLAPI_ATTR_VALUE_TOMBSTONE); */
/* JCMREPL - Add a description of what's going on? */
}
@@ -1032,17 +1018,7 @@ common_return:
* but not if the operation is purging tombstones.
*/
if (!delete_tombstone_entry) {
- if (e) {
- /* set entry in case be-postop plugins need to work on it
- * (e.g., USN) */
- slapi_pblock_get( pb, SLAPI_DELETE_BEPOSTOP_ENTRY, &orig_entry );
- slapi_pblock_set( pb, SLAPI_DELETE_BEPOSTOP_ENTRY, e->ep_entry );
- }
plugin_call_plugins (pb, SLAPI_PLUGIN_BE_POST_DELETE_FN);
- /* set original entry back */
- if (e) {
- slapi_pblock_set( pb, SLAPI_DELETE_BEPOSTOP_ENTRY, orig_entry );
- }
}
/* Need to return to cache after post op plugins are called */
11 years, 6 months
Branch '389-ds-base-1.2.11' - ldap/servers
by Richard Allen Megginson
ldap/servers/plugins/replication/repl5_protocol_util.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
New commits:
commit 5769e192e220b8630b7ed6edc22b11d10f94730a
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Mon May 21 09:08:04 2012 -0600
Ticket #321 - krbExtraData is being null modified and replicated on each ssh login
Bug Description: Crash during IPA install
Fix Description: Have to free the mod before moving the unremoved mods
down the list on top of the freed mod.
Reviewed by: mreynolds (Thanks!)
(cherry picked from commit 758a68db83c653187203d683c9d9a71742314be5)
diff --git a/ldap/servers/plugins/replication/repl5_protocol_util.c b/ldap/servers/plugins/replication/repl5_protocol_util.c
index 3327405..30d211a 100644
--- a/ldap/servers/plugins/replication/repl5_protocol_util.c
+++ b/ldap/servers/plugins/replication/repl5_protocol_util.c
@@ -707,6 +707,11 @@ repl5_strip_fractional_mods(Repl_Agmt *agmt, LDAPMod ** mods)
*/
if (0 == slapi_attr_type_cmp(mods[j]->mod_type, a[i], SLAPI_TYPE_CMP_SUBTYPE))
{
+ /* Adjust value of j, implicit in not incrementing it */
+ /* Free this mod */
+ ber_bvecfree(mods[j]->mod_bvalues);
+ slapi_ch_free((void **)&(mods[j]->mod_type));
+ slapi_ch_free((void **)&mods[j]);
/* Move down all subsequent mods */
for (k = j; mods[k+1] ; k++)
{
@@ -714,11 +719,6 @@ repl5_strip_fractional_mods(Repl_Agmt *agmt, LDAPMod ** mods)
}
/* Zero the end of the array */
mods[k] = NULL;
- /* Adjust value of j, implicit in not incrementing it */
- /* Free this mod */
- ber_bvecfree(mods[j]->mod_bvalues);
- slapi_ch_free((void **)&(mods[j]->mod_type));
- slapi_ch_free((void **)&mods[j]);
} else {
j++;
}
11 years, 6 months