Branch '389-ds-base-1.2.10' - 2 commits - ldap/servers VERSION.sh
by Richard Allen Megginson
VERSION.sh | 2 -
ldap/servers/slapd/ldaputil.c | 36 ++++++++++++++++++++++++
ldap/servers/slapd/tools/ldclt/ldapfct.c | 25 ++++++++++++++++
ldap/servers/slapd/tools/rsearch/addthread.c | 26 +++++++++++++++++
ldap/servers/slapd/tools/rsearch/searchthread.c | 32 +++++++++++++++++++++
5 files changed, 120 insertions(+), 1 deletion(-)
New commits:
commit 4aa5ed3e39357baf124f2fdc3c8cf02f613429c5
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Mon Apr 30 09:51:25 2012 -0600
bump version to 1.2.10.7
diff --git a/VERSION.sh b/VERSION.sh
index 7ee84c0..f5117a7 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=10.6
+VERSION_MAINT=10.7
# if this is a PRERELEASE, set VERSION_PREREL
# otherwise, comment it out
# be sure to include the dot prefix in the prerel
commit 3f73fa545d6e0edb9b4620be057e564ee5067276
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Tue Apr 24 20:09:38 2012 -0600
Ticket #348 - crash in ldap_initialize with multiple threads
https://fedorahosted.org/389/ticket/348
Resolves: Ticket #348
Bug Description: crash in ldap_initialize with multiple threads
Reviewed by: mreynolds (Thanks!)
Branch: master
Fix Description: Protect calls to ldap_initialize() with a mutex to prevent
multiple threads from calling it at the same time.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
(cherry picked from commit 23c088919f66de014ee7f9aad407468e51451405)
diff --git a/ldap/servers/slapd/ldaputil.c b/ldap/servers/slapd/ldaputil.c
index 545c703..80ab8cb 100644
--- a/ldap/servers/slapd/ldaputil.c
+++ b/ldap/servers/slapd/ldaputil.c
@@ -99,6 +99,24 @@
#if !defined(USE_OPENLDAP)
#include <ldap_ssl.h>
#include <ldappr.h>
+#else
+/* need mutex around ldap_initialize - see https://fedorahosted.org/389/ticket/348 */
+static PRCallOnceType ol_init_callOnce = {0,0};
+static PRLock *ol_init_lock = NULL;
+
+static PRStatus
+internal_ol_init_init(void)
+{
+ PR_ASSERT(NULL == ol_init_lock);
+ if ((ol_init_lock = PR_NewLock()) == NULL) {
+ PRErrorCode errorCode = PR_GetError();
+ slapi_log_error(SLAPI_LOG_FATAL, "internal_ol_init_init", "PR_NewLock failed %d:%s\n",
+ errorCode, slapd_pr_strerror(errorCode));
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
#endif
/* the server depends on the old, deprecated ldap_explode behavior which openldap
@@ -737,7 +755,16 @@ slapi_ldap_init_ext(
#if defined(USE_OPENLDAP)
if (ldapurl) {
+ if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
+ slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext",
+ "Could not perform internal ol_init init\n");
+ rc = -1;
+ goto done;
+ }
+
+ PR_Lock(ol_init_lock);
rc = ldap_initialize(&ld, ldapurl);
+ PR_Unlock(ol_init_lock);
if (rc) {
slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext",
"Could not initialize LDAP connection to [%s]: %d:%s\n",
@@ -751,7 +778,16 @@ slapi_ldap_init_ext(
} else { /* host port */
makeurl = convert_to_openldap_uri(hostname, port, (secure == 1 ? "ldaps" : "ldap"));
}
+ if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
+ slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext",
+ "Could not perform internal ol_init init\n");
+ rc = -1;
+ goto done;
+ }
+
+ PR_Lock(ol_init_lock);
rc = ldap_initialize(&ld, makeurl);
+ PR_Unlock(ol_init_lock);
if (rc) {
slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext",
"Could not initialize LDAP connection to [%s]: %d:%s\n",
diff --git a/ldap/servers/slapd/tools/ldclt/ldapfct.c b/ldap/servers/slapd/tools/ldclt/ldapfct.c
index 0e8a2fb..3f74fd0 100644
--- a/ldap/servers/slapd/tools/ldclt/ldapfct.c
+++ b/ldap/servers/slapd/tools/ldclt/ldapfct.c
@@ -708,6 +708,23 @@ done:
return rc;
}
+
+/* need mutex around ldap_initialize - see https://fedorahosted.org/389/ticket/348 */
+static PRCallOnceType ol_init_callOnce = {0,0};
+static PRLock *ol_init_lock = NULL;
+
+static PRStatus
+internal_ol_init_init(void)
+{
+ PR_ASSERT(NULL == ol_init_lock);
+ if ((ol_init_lock = PR_NewLock()) == NULL) {
+ PRErrorCode errorCode = PR_GetError();
+ printf("internal_ol_init_init PR_NewLock failed %d\n", errorCode);
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
#endif /* USE_OPENLDAP */
/* mctx is a global */
@@ -735,12 +752,20 @@ connectToLDAP(thread_context *tttctx, const char *bufBindDN, const char *bufPass
ldapurl = PR_smprintf("ldap%s://%s:%d/",
(mode & SSL) ? "s" : "",
mctx.hostname, mctx.port);
+ if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
+ printf("Could not perform internal ol_init init\n");
+ goto done;
+ }
+
+ PR_Lock(ol_init_lock);
if ((ret = ldap_initialize(&ld, ldapurl))) {
+ PR_Unlock(ol_init_lock);
printf ("ldclt[%d]: T%03d: Cannot ldap_initialize (%s), errno=%d ldaperror=%d:%s\n",
mctx.pid, thrdNum, ldapurl, errno, ret, my_ldap_err2string(ret));
fflush (stdout);
goto done;
}
+ PR_Unlock(ol_init_lock);
PR_smprintf_free(ldapurl);
ldapurl = NULL;
if (mode & SSL) {
diff --git a/ldap/servers/slapd/tools/rsearch/addthread.c b/ldap/servers/slapd/tools/rsearch/addthread.c
index f01ba18..a3e5568 100644
--- a/ldap/servers/slapd/tools/rsearch/addthread.c
+++ b/ldap/servers/slapd/tools/rsearch/addthread.c
@@ -176,6 +176,25 @@ static void at_disconnect(AddThread *at)
}
#endif
+#if defined(USE_OPENLDAP)
+/* need mutex around ldap_initialize - see https://fedorahosted.org/389/ticket/348 */
+static PRCallOnceType ol_init_callOnce = {0,0};
+static PRLock *ol_init_lock = NULL;
+
+static PRStatus
+internal_ol_init_init(void)
+{
+ PR_ASSERT(NULL == ol_init_lock);
+ if ((ol_init_lock = PR_NewLock()) == NULL) {
+ PRErrorCode errorCode = PR_GetError();
+ fprintf(stderr, "internal_ol_init_init PR_NewLock failed %d\n", errorCode);
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
+#endif
+
static void at_bind(AddThread *at)
{
int ret;
@@ -185,7 +204,14 @@ static void at_bind(AddThread *at)
at->ld = NULL;
ldapurl = PR_smprintf("ldap://%s:%d", hostname, port);
+ if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
+ fprintf(stderr, "Could not perform internal ol_init init\n");
+ return;
+ }
+
+ PR_Lock(ol_init_lock);
ret = ldap_initialize(&at->ld, ldapurl);
+ PR_Unlock(ol_init_lock);
PR_smprintf_free(ldapurl);
ldapurl = NULL;
if (ret) {
diff --git a/ldap/servers/slapd/tools/rsearch/searchthread.c b/ldap/servers/slapd/tools/rsearch/searchthread.c
index 9e2b0d6..8a74d58 100644
--- a/ldap/servers/slapd/tools/rsearch/searchthread.c
+++ b/ldap/servers/slapd/tools/rsearch/searchthread.c
@@ -180,6 +180,24 @@ static int st_bind_core(SearchThread *st, LDAP **ld, char *dn, char *pw)
return 1;
}
+#if defined(USE_OPENLDAP)
+/* need mutex around ldap_initialize - see https://fedorahosted.org/389/ticket/348 */
+static PRCallOnceType ol_init_callOnce = {0,0};
+static PRLock *ol_init_lock = NULL;
+
+static PRStatus
+internal_ol_init_init(void)
+{
+ PR_ASSERT(NULL == ol_init_lock);
+ if ((ol_init_lock = PR_NewLock()) == NULL) {
+ PRErrorCode errorCode = PR_GetError();
+ fprintf(stderr, "internal_ol_init_init PR_NewLock failed %d\n", errorCode);
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
+#endif
static int st_bind(SearchThread *st)
{
if (!st->ld) {
@@ -189,7 +207,14 @@ static int st_bind(SearchThread *st)
st->ld = NULL;
ldapurl = PR_smprintf("ldap://%s:%d", hostname, port);
+ if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
+ fprintf(stderr, "Could not perform internal ol_init init\n");
+ return 0;
+ }
+
+ PR_Lock(ol_init_lock);
ret = ldap_initialize(&st->ld, ldapurl);
+ PR_Unlock(ol_init_lock);
PR_smprintf_free(ldapurl);
ldapurl = NULL;
if (ret) {
@@ -212,7 +237,14 @@ static int st_bind(SearchThread *st)
st->ld2 = NULL;
ldapurl = PR_smprintf("ldap://%s:%d", hostname, port);
+ if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
+ fprintf(stderr, "Could not perform internal ol_init init\n");
+ return 0;
+ }
+
+ PR_Lock(ol_init_lock);
ret = ldap_initialize(&st->ld2, ldapurl);
+ PR_Unlock(ol_init_lock);
PR_smprintf_free(ldapurl);
ldapurl = NULL;
if (ret) {
11 years, 1 month
ldap/servers
by Noriko Hosoi
ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c | 523 ++++++++++++++++++---------
ldap/servers/slapd/log.c | 2
ldap/servers/slapd/slapi-plugin.h | 2
3 files changed, 357 insertions(+), 170 deletions(-)
New commits:
commit dd65701e7c6e2c3ebd40f71db6b5c64d1073d0f6
Author: Noriko Hosoi <nhosoi(a)totoro.usersys.redhat.com>
Date: Mon Apr 30 09:28:41 2012 -0700
Trac Ticket #345 - db deadlock return should not log error
https://fedorahosted.org/389/ticket/345
Fix description:
1) In the ldbm_entryrdn.c, error log level is set to
SLAPI_LOG_BACKLDBM if DB_LOCK_DEADLOCK is returned
from the BDB operations, otherwise set to SLAPI_LOG_FATAL.
2) If DB_LOCK_DEADLOCK is returned in the entryrdn functions,
retry the BDB operations up to RETRY_TIMES.
3) The log level of ACLSUMMARY and the one of BACKLDBM were
confused. It was fixed in log.c.
Reviewed by Rich (Thanks!!)
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
index 4eba4ed..5281f22 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
@@ -63,6 +63,16 @@ static int entryrdn_noancestorid = 0;
#define ASSERT(_x) ;
#endif
+#define ENTRYRDN_LOGLEVEL(rc) \
+ (((rc)==DB_LOCK_DEADLOCK)?SLAPI_LOG_BACKLDBM:SLAPI_LOG_FATAL)
+
+#define ENTRYRDN_DELAY \
+{ \
+ PRIntervalTime interval; \
+ interval = PR_MillisecondsToInterval(slapi_rand() % 100); \
+ DS_Sleep(interval); \
+}
+
#define ENTRYRDN_TAG "entryrdn-index"
#define RDN_INDEX_SELF 'S'
@@ -213,6 +223,7 @@ entryrdn_index_entry(backend *be,
DB_TXN *db_txn = (txn != NULL) ? txn->back_txn_txn : NULL;
const Slapi_DN *sdn = NULL;
Slapi_RDN *srdn = NULL;
+ int db_retry = 0;
slapi_log_error(SLAPI_LOG_TRACE, ENTRYRDN_TAG,
"--> entryrdn_index_entry\n");
@@ -257,13 +268,21 @@ entryrdn_index_entry(backend *be,
}
/* Make a cursor */
- rc = db->cursor(db, db_txn, &cursor, 0);
- if (rc) {
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
- "entryrdn_index_entry: Failed to make a cursor: %s(%d)\n",
- dblayer_strerror(rc), rc);
- cursor = NULL;
- goto bail;
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = db->cursor(db, db_txn, &cursor, 0);
+ if (rc) {
+ 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) {
+ ENTRYRDN_DELAY;
+ continue;
+ }
+ cursor = NULL;
+ goto bail;
+ } else {
+ break; /* success */
+ }
}
if (flags & BE_INDEX_ADD) {
@@ -278,16 +297,24 @@ entryrdn_index_entry(backend *be,
bail:
/* Close the cursor */
if (cursor) {
- int myrc = cursor->c_close(cursor);
- if (0 != myrc) {
- int loglevel = (myrc == DB_LOCK_DEADLOCK) ? SLAPI_LOG_TRACE : SLAPI_LOG_FATAL;
- slapi_log_error(loglevel, ENTRYRDN_TAG,
- "entryrdn_index_entry: Failed to close cursor: %s(%d)\n",
- dblayer_strerror(myrc), myrc);
- if (!rc) {
- /* if cursor close returns DEADLOCK, we must bubble that up
- to the higher layers for retries */
- rc = myrc;
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ int myrc = cursor->c_close(cursor);
+ if (0 != myrc) {
+ 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) {
+ ENTRYRDN_DELAY;
+ continue;
+ }
+ if (!rc) {
+ /* if cursor close returns DEADLOCK, we must bubble that up
+ to the higher layers for retries */
+ rc = myrc;
+ break;
+ }
+ } else {
+ break; /* success */
}
}
}
@@ -332,6 +359,7 @@ entryrdn_index_read_ext(backend *be,
DB_TXN *db_txn = (txn != NULL) ? txn->back_txn_txn : NULL;
DBC *cursor = NULL;
rdn_elem *elem = NULL;
+ int db_retry = 0;
slapi_log_error(SLAPI_LOG_TRACE, ENTRYRDN_TAG,
"--> entryrdn_index_read\n");
@@ -373,13 +401,21 @@ entryrdn_index_read_ext(backend *be,
}
/* Make a cursor */
- rc = db->cursor(db, db_txn, &cursor, 0);
- if (rc) {
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
- "entryrdn_index_read: Failed to make a cursor: %s(%d)\n",
- dblayer_strerror(rc), rc);
- cursor = NULL;
- goto bail;
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = db->cursor(db, db_txn, &cursor, 0);
+ if (rc) {
+ 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) {
+ ENTRYRDN_DELAY;
+ continue;
+ }
+ cursor = NULL;
+ goto bail;
+ } else {
+ break; /* success */
+ }
}
rc = _entryrdn_index_read(be, cursor, &srdn, &elem, NULL, NULL,
@@ -392,16 +428,24 @@ entryrdn_index_read_ext(backend *be,
bail:
/* Close the cursor */
if (cursor) {
- int myrc = cursor->c_close(cursor);
- if (0 != myrc) {
- int loglevel = (myrc == DB_LOCK_DEADLOCK) ? SLAPI_LOG_TRACE : SLAPI_LOG_FATAL;
- slapi_log_error(loglevel, ENTRYRDN_TAG,
- "entryrdn_index_read: Failed to close cursor: %s(%d)\n",
- dblayer_strerror(myrc), myrc);
- if (!rc) {
- /* if cursor close returns DEADLOCK, we must bubble that up
- to the higher layers for retries */
- rc = myrc;
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ int myrc = cursor->c_close(cursor);
+ if (0 != myrc) {
+ 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) {
+ ENTRYRDN_DELAY;
+ continue;
+ }
+ if (!rc) {
+ /* if cursor close returns DEADLOCK, we must bubble that up
+ to the higher layers for retries */
+ rc = myrc;
+ break;
+ }
+ } else {
+ break; /* success */
}
}
}
@@ -461,6 +505,7 @@ entryrdn_rename_subtree(backend *be,
const Slapi_DN *mynewsupsdn = NULL;
Slapi_RDN *mynewsrdn = NULL;
ID targetid = 0;
+ int db_retry = 0;
slapi_log_error(SLAPI_LOG_TRACE, ENTRYRDN_TAG,
"--> entryrdn_rename_subtree\n");
@@ -542,13 +587,21 @@ entryrdn_rename_subtree(backend *be,
}
/* Make a cursor */
- rc = db->cursor(db, db_txn, &cursor, 0);
- if (rc) {
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
- "entryrdn_rename_subtree: Failed to make a cursor: %s(%d)\n",
- dblayer_strerror(rc), rc);
- cursor = NULL;
- goto bail;
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = db->cursor(db, db_txn, &cursor, 0);
+ if (rc) {
+ 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) {
+ ENTRYRDN_DELAY;
+ continue;
+ }
+ cursor = NULL;
+ goto bail;
+ } else {
+ break; /* success */
+ }
}
/* prepare the element for the newly renamed rdn, if any. */
@@ -663,7 +716,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.flags = DB_DBT_USERMEM;
rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_SELF);
if (rc) {
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_rename_subtree: Adding %s failed; "
"%s(%d)\n", keybuf, dblayer_strerror(rc), rc);
goto bail;
@@ -735,7 +788,7 @@ entryrdn_rename_subtree(backend *be,
}
rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_PARENT);
if (rc) {
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_rename_subtree: Adding "
"%s failed; %s(%d)\n",
keybuf, dblayer_strerror(rc), rc);
@@ -770,7 +823,7 @@ entryrdn_rename_subtree(backend *be,
renamedata.flags = DB_DBT_USERMEM;
rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_SELF);
if (rc) {
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"entryrdn_rename_subtree: Adding %s failed; "
"%s(%d)\n", keybuf, dblayer_strerror(rc), rc);
goto bail;
@@ -851,16 +904,24 @@ bail:
/* Close the cursor */
if (cursor) {
- int myrc = cursor->c_close(cursor);
- if (0 != myrc) {
- int loglevel = (myrc == DB_LOCK_DEADLOCK) ? SLAPI_LOG_TRACE : SLAPI_LOG_FATAL;
- slapi_log_error(loglevel, ENTRYRDN_TAG,
- "entryrdn_rename_subtree: Failed to close cursor: %s(%d)\n",
- dblayer_strerror(myrc), myrc);
- if (!rc) {
- /* if cursor close returns DEADLOCK, we must bubble that up
- to the higher layers for retries */
- rc = myrc;
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ int myrc = cursor->c_close(cursor);
+ if (0 != myrc) {
+ 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) {
+ ENTRYRDN_DELAY;
+ continue;
+ }
+ if (!rc) {
+ /* if cursor close returns DEADLOCK, we must bubble that up
+ to the higher layers for retries */
+ rc = myrc;
+ break;
+ }
+ } else {
+ break; /* success */
}
}
}
@@ -895,6 +956,7 @@ entryrdn_get_subordinates(backend *be,
rdn_elem *elem = NULL;
rdn_elem **childelems = NULL;
rdn_elem **cep = NULL;
+ int db_retry = 0;
slapi_log_error(SLAPI_LOG_TRACE, ENTRYRDN_TAG,
"--> entryrdn_get_subordinates\n");
@@ -948,13 +1010,21 @@ entryrdn_get_subordinates(backend *be,
}
/* Make a cursor */
- rc = db->cursor(db, db_txn, &cursor, 0);
- if (rc) {
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
- "entryrdn_get_subordinates: Failed to make a cursor: %s(%d)\n",
- dblayer_strerror(rc), rc);
- cursor = NULL;
- goto bail;
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = db->cursor(db, db_txn, &cursor, 0);
+ if (rc) {
+ 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) {
+ ENTRYRDN_DELAY;
+ continue;
+ }
+ cursor = NULL;
+ goto bail;
+ } else {
+ break; /* success */
+ }
}
rc = _entryrdn_index_read(be, cursor, &srdn, &elem,
@@ -999,16 +1069,24 @@ bail:
/* Close the cursor */
if (cursor) {
- int myrc = cursor->c_close(cursor);
- if (0 != myrc) {
- int loglevel = (myrc == DB_LOCK_DEADLOCK) ? SLAPI_LOG_TRACE : SLAPI_LOG_FATAL;
- slapi_log_error(loglevel, ENTRYRDN_TAG,
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ int myrc = cursor->c_close(cursor);
+ if (0 != myrc) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(myrc), ENTRYRDN_TAG,
"entryrdn_get_subordinates: Failed to close cursor: %s(%d)\n",
dblayer_strerror(myrc), myrc);
- if (!rc) {
- /* if cursor close returns DEADLOCK, we must bubble that up
- to the higher layers for retries */
- rc = myrc;
+ if (DB_LOCK_DEADLOCK == myrc) {
+ ENTRYRDN_DELAY;
+ continue;
+ }
+ if (!rc) {
+ /* if cursor close returns DEADLOCK, we must bubble that up
+ to the higher layers for retries */
+ rc = myrc;
+ break;
+ }
+ } else {
+ break; /* success */
}
}
}
@@ -1047,6 +1125,7 @@ entryrdn_lookup_dn(backend *be,
ID workid = id; /* starting from the given id */
rdn_elem *elem = NULL;
int maybesuffix = 0;
+ int db_retry = 0;
slapi_log_error(SLAPI_LOG_TRACE, ENTRYRDN_TAG,
"--> entryrdn_lookup_dn\n");
@@ -1072,13 +1151,21 @@ entryrdn_lookup_dn(backend *be,
memset(&data, 0, sizeof(data));
/* Make a cursor */
- rc = db->cursor(db, db_txn, &cursor, 0);
- if (rc) {
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
- "entryrdn_lookup_dn: Failed to make a cursor: %s(%d)\n",
- dblayer_strerror(rc), rc);
- cursor = NULL;
- goto bail;
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = db->cursor(db, db_txn, &cursor, 0);
+ if (rc) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "entryrdn_lookup_dn: Failed to make a cursor: %s(%d)\n",
+ dblayer_strerror(rc), rc);
+ if (DB_LOCK_DEADLOCK == rc) {
+ ENTRYRDN_DELAY;
+ continue;
+ }
+ cursor = NULL;
+ goto bail;
+ } else {
+ break; /* success */
+ }
}
srdn = slapi_rdn_new_all_dn(rdn);
orignrdn = slapi_ch_strdup(rdn);
@@ -1169,16 +1256,24 @@ bail:
slapi_ch_free(&data.data);
/* Close the cursor */
if (cursor) {
- int myrc = cursor->c_close(cursor);
- if (0 != myrc) {
- int loglevel = (myrc == DB_LOCK_DEADLOCK) ? SLAPI_LOG_TRACE : SLAPI_LOG_FATAL;
- slapi_log_error(loglevel, ENTRYRDN_TAG,
- "entryrdn_lookup_dn: Failed to close cursor: %s(%d)\n",
- dblayer_strerror(myrc), myrc);
- if (!rc) {
- /* if cursor close returns DEADLOCK, we must bubble that up
- to the higher layers for retries */
- rc = myrc;
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ int myrc = cursor->c_close(cursor);
+ if (0 != myrc) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(myrc), ENTRYRDN_TAG,
+ "entryrdn_lookup_dn: Failed to close cursor: %s(%d)\n",
+ dblayer_strerror(myrc), myrc);
+ if (DB_LOCK_DEADLOCK == myrc) {
+ ENTRYRDN_DELAY;
+ continue;
+ }
+ if (!rc) {
+ /* if cursor close returns DEADLOCK, we must bubble that up
+ to the higher layers for retries */
+ rc = myrc;
+ break;
+ }
+ } else {
+ break; /* success */
}
}
}
@@ -1219,6 +1314,7 @@ entryrdn_get_parent(backend *be,
char *nrdn = NULL;
size_t nrdn_len = 0;
rdn_elem *elem = NULL;
+ int db_retry = 0;
slapi_log_error(SLAPI_LOG_TRACE, ENTRYRDN_TAG,
"--> entryrdn_get_parent\n");
@@ -1248,13 +1344,21 @@ entryrdn_get_parent(backend *be,
}
/* Make a cursor */
- rc = db->cursor(db, db_txn, &cursor, 0);
- if (rc) {
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
- "entryrdn_get_parent: Failed to make a cursor: %s(%d)\n",
- dblayer_strerror(rc), rc);
- cursor = NULL;
- goto bail;
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = db->cursor(db, db_txn, &cursor, 0);
+ if (rc) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "entryrdn_get_parent: Failed to make a cursor: %s(%d)\n",
+ dblayer_strerror(rc), rc);
+ if (DB_LOCK_DEADLOCK == rc) {
+ ENTRYRDN_DELAY;
+ continue;
+ }
+ cursor = NULL;
+ goto bail;
+ } else {
+ break; /* success */
+ }
}
orignrdn = slapi_ch_strdup(rdn);
rc = slapi_dn_normalize_case_ext(orignrdn, 0, &nrdn, &nrdn_len);
@@ -1322,16 +1426,24 @@ bail:
slapi_ch_free((void **)&data.data);
/* Close the cursor */
if (cursor) {
- int myrc = cursor->c_close(cursor);
- if (0 != myrc) {
- int loglevel = (myrc == DB_LOCK_DEADLOCK) ? SLAPI_LOG_TRACE : SLAPI_LOG_FATAL;
- slapi_log_error(loglevel, ENTRYRDN_TAG,
- "entryrdn_get_parent: Failed to close cursor: %s(%d)\n",
- dblayer_strerror(myrc), myrc);
- if (!rc) {
- /* if cursor close returns DEADLOCK, we must bubble that up
- to the higher layers for retries */
- rc = myrc;
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ int myrc = cursor->c_close(cursor);
+ if (0 != myrc) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(myrc), ENTRYRDN_TAG,
+ "entryrdn_get_parent: Failed to close cursor: %s(%d)\n",
+ dblayer_strerror(myrc), myrc);
+ if (DB_LOCK_DEADLOCK == myrc) {
+ ENTRYRDN_DELAY;
+ continue;
+ }
+ if (!rc) {
+ /* if cursor close returns DEADLOCK, we must bubble that up
+ to the higher layers for retries */
+ rc = myrc;
+ break;
+ }
+ } else {
+ break; /* success */
}
}
}
@@ -1732,6 +1844,7 @@ static int
_entryrdn_put_data(DBC *cursor, DBT *key, DBT *data, char type)
{
int rc = -1;
+ int db_retry = 0;
slapi_log_error(SLAPI_LOG_TRACE, ENTRYRDN_TAG,
"--> _entryrdn_put_data\n");
@@ -1743,27 +1856,36 @@ _entryrdn_put_data(DBC *cursor, DBT *key, DBT *data, char type)
goto bail;
}
/* insert it */
- rc = cursor->c_put(cursor, key, data, DB_NODUPDATA);
- if (rc) {
- if (DB_KEYEXIST == rc) {
- /* this is okay */
- slapi_log_error(SLAPI_LOG_BACKLDBM, ENTRYRDN_TAG,
- "_entryrdn_put_data: The same key (%s) and the "
- "data exists in index\n",
- (char *)key->data);
- } else {
- char *keyword = NULL;
- if (type == RDN_INDEX_CHILD) {
- keyword = "child";
- } else if (type == RDN_INDEX_PARENT) {
- keyword = "parent";
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = cursor->c_put(cursor, key, data, DB_NODUPDATA);
+ if (rc) {
+ if (DB_KEYEXIST == rc) {
+ /* this is okay */
+ slapi_log_error(SLAPI_LOG_BACKLDBM, ENTRYRDN_TAG,
+ "_entryrdn_put_data: The same key (%s) and the "
+ "data exists in index\n",
+ (char *)key->data);
} else {
- keyword = "self";
+ char *keyword = NULL;
+ if (type == RDN_INDEX_CHILD) {
+ keyword = "child";
+ } else if (type == RDN_INDEX_PARENT) {
+ keyword = "parent";
+ } else {
+ keyword = "self";
+ }
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_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) {
+ ENTRYRDN_DELAY;
+ continue;
+ }
+ goto bail;
}
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
- "_entryrdn_put_data: Adding the %s link (%s) "
- "failed: %s (%d)\n", keyword, (char *)key->data,
- dblayer_strerror(rc), rc);
+ } else {
+ break; /* success */
}
}
bail:
@@ -1775,6 +1897,7 @@ static int
_entryrdn_del_data(DBC *cursor, DBT *key, DBT *data)
{
int rc = -1;
+ int db_retry = 0;
slapi_log_error(SLAPI_LOG_TRACE, ENTRYRDN_TAG,
"--> _entryrdn_del_data\n");
@@ -1799,12 +1922,21 @@ retry_get:
}
} else {
/* We found it, so delete it */
- rc = cursor->c_del(cursor, 0);
- if (rc) {
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
- "_entryrdn_del_data: Deleting %s failed; "
- "%s(%d)\n", (char *)key->data,
- dblayer_strerror(rc), rc);
+ 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) {
+ ENTRYRDN_DELAY;
+ continue;
+ }
+ goto bail;
+ } else {
+ break; /* success */
+ }
}
}
bail:
@@ -1917,16 +2049,25 @@ _entryrdn_replace_suffix_id(DBC *cursor, DBT *key, DBT *adddata,
rdn_elem *childelem = NULL;
size_t childnum = 4;
size_t curr_childnum = 0;
+ int db_retry = 0;
/* temporary id added for the non exisiting suffix */
/* Let's replace it with the real entry ID */
/* SELF */
- rc = cursor->c_put(cursor, key, adddata, DB_CURRENT);
- if (rc) {
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = cursor->c_put(cursor, key, adddata, DB_CURRENT);
+ if (rc) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"_entryrdn_replace_suffix_id: Adding suffix %s failed: "
"%s (%d)\n", normsuffix, dblayer_strerror(rc), rc);
- goto bail;
+ if (DB_LOCK_DEADLOCK == rc) {
+ ENTRYRDN_DELAY;
+ continue;
+ }
+ goto bail;
+ } else {
+ break; /* success */
+ }
}
/*
@@ -2051,13 +2192,21 @@ retry_get2:
/* the parent id is TMPID;
* replace it with the given id */
id_internal_to_stored(id, pelem->rdn_elem_id);
- rc = cursor->c_put(cursor, key, &moddata, DB_CURRENT);
- if (rc) {
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = cursor->c_put(cursor, key, &moddata, DB_CURRENT);
+ if (rc) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"_entryrdn_replace_suffix_id: "
"Fixing the parent link (%s) failed: %s (%d)\n",
keybuf, dblayer_strerror(rc), rc);
- goto bail0;
+ if (DB_LOCK_DEADLOCK == rc) {
+ ENTRYRDN_DELAY;
+ continue;
+ }
+ goto bail0;
+ } else {
+ break; /* success */
+ }
}
}
slapi_ch_free((void **)&moddata.data);
@@ -2098,6 +2247,7 @@ _entryrdn_insert_key(backend *be,
rdn_elem *parentelem = NULL;
rdn_elem *tmpelem = NULL;
Slapi_RDN *tmpsrdn = NULL;
+ int db_retry = 0;
slapi_log_error(SLAPI_LOG_TRACE, ENTRYRDN_TAG,
"--> _entryrdn_insert_key\n");
@@ -2150,13 +2300,21 @@ _entryrdn_insert_key(backend *be,
ID tmpid;
memset(&existdata, 0, sizeof(existdata));
existdata.flags = DB_DBT_MALLOC;
- rc = cursor->c_get(cursor, &key, &existdata, DB_SET);
- if (rc) {
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = cursor->c_get(cursor, &key, &existdata, DB_SET);
+ if (rc) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"_entryrdn_insert_key: Get existing suffix %s "
"failed: %s (%d)\n",
nrdn, dblayer_strerror(rc), rc);
- goto bail;
+ if (DB_LOCK_DEADLOCK == rc) {
+ ENTRYRDN_DELAY;
+ continue;
+ }
+ goto bail;
+ } else {
+ break; /* success */
+ }
}
existelem = (rdn_elem *)existdata.data;
tmpid = id_stored_to_internal(existelem->rdn_elem_id);
@@ -2247,7 +2405,7 @@ _entryrdn_insert_key(backend *be,
"_entryrdn_insert_key: Suffix %s added: %d\n",
slapi_rdn_get_rdn(tmpsrdn), rc);
} else {
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"_entryrdn_insert_key: Suffix \"%s\" not found: "
"%s(%d)\n", nrdn, dblayer_strerror(rc), rc);
goto bail;
@@ -2347,7 +2505,7 @@ _entryrdn_insert_key(backend *be,
"_entryrdn_insert_key: Node \"%s\" not found: "
"%s(%d)\n", dn, dblayer_strerror(rc), rc);
} else {
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"_entryrdn_insert_key: Getting \"%s\" failed: "
"%s(%d)\n", dn, dblayer_strerror(rc), rc);
}
@@ -2367,7 +2525,7 @@ _entryrdn_insert_key(backend *be,
} else {
char *dn = NULL;
slapi_rdn_get_dn(tmpsrdn, &dn);
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
"_entryrdn_insert_key: Suffix \"%s\" not found: "
"%s(%d)\n", nrdn, dblayer_strerror(rc), rc);
slapi_ch_free_string(&dn);
@@ -2452,6 +2610,7 @@ _entryrdn_delete_key(backend *be,
rdn_elem *elem = NULL;
int issuffix = 0;
Slapi_RDN *tmpsrdn = NULL;
+ int db_retry = 0;
slapi_log_error(SLAPI_LOG_TRACE, ENTRYRDN_TAG,
"--> _entryrdn_delete_key\n");
@@ -2610,13 +2769,21 @@ retry_get0:
/* deleteing the parent link */
/* the cursor is set at the parent link by _entryrdn_get_elem */
- rc = cursor->c_del(cursor, 0);
- if (rc && DB_NOTFOUND != rc) {
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
- "_entryrdn_delete_key: Deleting %s failed; "
- "%s(%d)\n", (char *)key.data,
- dblayer_strerror(rc), rc);
- goto bail;
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = cursor->c_del(cursor, 0);
+ if (rc && (DB_NOTFOUND != rc)) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_delete_key: Deleting %s failed; "
+ "%s(%d)\n", (char *)key.data,
+ dblayer_strerror(rc), rc);
+ if (DB_LOCK_DEADLOCK == rc) {
+ ENTRYRDN_DELAY;
+ continue;
+ }
+ goto bail;
+ } else {
+ break; /* success */
+ }
}
} else if (parentnrdn) {
#ifdef LDAP_DEBUG_ENTRYRDN
@@ -2625,13 +2792,21 @@ retry_get0:
slapi_ch_free_string(&parentnrdn);
/* deleteing the parent's child link */
/* the cursor is set at the parent link by _entryrdn_get_elem */
- rc = cursor->c_del(cursor, 0);
- if (rc && DB_NOTFOUND != rc) {
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
- "_entryrdn_delete_key: Deleting %s failed; "
- "%s(%d)\n", (char *)key.data,
- dblayer_strerror(rc), rc);
- goto bail;
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = cursor->c_del(cursor, 0);
+ if (rc && (DB_NOTFOUND != rc)) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_delete_key: Deleting %s failed; "
+ "%s(%d)\n", (char *)key.data,
+ dblayer_strerror(rc), rc);
+ if (DB_LOCK_DEADLOCK == rc) {
+ ENTRYRDN_DELAY;
+ continue;
+ }
+ goto bail;
+ } else {
+ break; /* success */
+ }
}
selfnrdn = nrdn;
workid = id;
@@ -2641,13 +2816,21 @@ retry_get0:
#endif
/* deleteing the self link */
/* the cursor is set at the parent link by _entryrdn_get_elem */
- rc = cursor->c_del(cursor, 0);
- if (rc && DB_NOTFOUND != rc) {
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
- "_entryrdn_delete_key: Deleting %s failed; "
- "%s(%d)\n", (char *)key.data,
- dblayer_strerror(rc), rc);
- goto bail;
+ for (db_retry = 0; db_retry < RETRY_TIMES; db_retry++) {
+ rc = cursor->c_del(cursor, 0);
+ if (rc && (DB_NOTFOUND != rc)) {
+ slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG,
+ "_entryrdn_delete_key: Deleting %s failed; "
+ "%s(%d)\n", (char *)key.data,
+ dblayer_strerror(rc), rc);
+ if (DB_LOCK_DEADLOCK == rc) {
+ ENTRYRDN_DELAY;
+ continue;
+ }
+ goto bail;
+ } else {
+ break; /* success */
+ }
}
goto bail; /* done */
}
@@ -2847,11 +3030,13 @@ _entryrdn_index_read(backend *be,
childnrdn, &tmpelem);
if (rc || (NULL == tmpelem)) {
slapi_ch_free((void **)&tmpelem);
- slapi_log_error(SLAPI_LOG_BACKLDBM, ENTRYRDN_TAG,
+ if (DB_NOTFOUND != rc) {
+ slapi_log_error(SLAPI_LOG_BACKLDBM, ENTRYRDN_TAG,
"_entryrdn_index_read: Child link \"%s\" of "
"key \"%s\" not found: %s(%d)\n",
childnrdn, keybuf, dblayer_strerror(rc), rc);
- rc = DB_NOTFOUND;
+ rc = DB_NOTFOUND;
+ }
if (tmpsrdn != srdn) {
slapi_rdn_free(&tmpsrdn);
}
@@ -2859,11 +3044,13 @@ _entryrdn_index_read(backend *be,
}
} else {
slapi_ch_free((void **)&tmpelem);
- slapi_log_error(SLAPI_LOG_BACKLDBM, ENTRYRDN_TAG,
+ if (DB_NOTFOUND != rc) {
+ slapi_log_error(SLAPI_LOG_BACKLDBM, ENTRYRDN_TAG,
"_entryrdn_index_read: Child link \"%s\" of "
"key \"%s\" not found: %s(%d)\n",
childnrdn, keybuf, dblayer_strerror(rc), rc);
- rc = DB_NOTFOUND;
+ rc = DB_NOTFOUND;
+ }
if (tmpsrdn != srdn) {
slapi_rdn_free(&tmpsrdn);
}
diff --git a/ldap/servers/slapd/log.c b/ldap/servers/slapd/log.c
index 60a49ab..2ffd1f6 100644
--- a/ldap/servers/slapd/log.c
+++ b/ldap/servers/slapd/log.c
@@ -102,8 +102,8 @@ static int slapi_log_map[] = {
LDAP_DEBUG_CACHE, /* SLAPI_LOG_CACHE */
LDAP_DEBUG_PLUGIN, /* SLAPI_LOG_PLUGIN */
LDAP_DEBUG_TIMING, /* SLAPI_LOG_TIMING */
- LDAP_DEBUG_ACLSUMMARY, /* SLAPI_LOG_ACLSUMMARY */
LDAP_DEBUG_BACKLDBM, /* SLAPI_LOG_BACKLDBM */
+ LDAP_DEBUG_ACLSUMMARY /* SLAPI_LOG_ACLSUMMARY */
};
#define SLAPI_LOG_MIN SLAPI_LOG_FATAL /* from slapi-plugin.h */
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index bef2356..215773b 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -5545,7 +5545,7 @@ int slapi_log_error( int severity, char *subsystem, char *fmt, ... )
#define SLAPI_LOG_PLUGIN 14
#define SLAPI_LOG_TIMING 15
#define SLAPI_LOG_BACKLDBM 16
-#define SLAPI_LOG_ACLSUMMARY 17
+#define SLAPI_LOG_ACLSUMMARY 17 /* ACLSUMMARY must be the last (log.c) */
int slapi_is_loglevel_set( const int loglevel );
11 years, 1 month
ldap/servers
by Richard Allen Megginson
ldap/servers/slapd/ldaputil.c | 36 ++++++++++++++++++++++++
ldap/servers/slapd/tools/ldclt/ldapfct.c | 25 ++++++++++++++++
ldap/servers/slapd/tools/rsearch/addthread.c | 26 +++++++++++++++++
ldap/servers/slapd/tools/rsearch/searchthread.c | 32 +++++++++++++++++++++
4 files changed, 119 insertions(+)
New commits:
commit 23c088919f66de014ee7f9aad407468e51451405
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Tue Apr 24 20:09:38 2012 -0600
Ticket #348 - crash in ldap_initialize with multiple threads
https://fedorahosted.org/389/ticket/348
Resolves: Ticket #348
Bug Description: crash in ldap_initialize with multiple threads
Reviewed by: mreynolds (Thanks!)
Branch: master
Fix Description: Protect calls to ldap_initialize() with a mutex to prevent
multiple threads from calling it at the same time.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
diff --git a/ldap/servers/slapd/ldaputil.c b/ldap/servers/slapd/ldaputil.c
index 545c703..80ab8cb 100644
--- a/ldap/servers/slapd/ldaputil.c
+++ b/ldap/servers/slapd/ldaputil.c
@@ -99,6 +99,24 @@
#if !defined(USE_OPENLDAP)
#include <ldap_ssl.h>
#include <ldappr.h>
+#else
+/* need mutex around ldap_initialize - see https://fedorahosted.org/389/ticket/348 */
+static PRCallOnceType ol_init_callOnce = {0,0};
+static PRLock *ol_init_lock = NULL;
+
+static PRStatus
+internal_ol_init_init(void)
+{
+ PR_ASSERT(NULL == ol_init_lock);
+ if ((ol_init_lock = PR_NewLock()) == NULL) {
+ PRErrorCode errorCode = PR_GetError();
+ slapi_log_error(SLAPI_LOG_FATAL, "internal_ol_init_init", "PR_NewLock failed %d:%s\n",
+ errorCode, slapd_pr_strerror(errorCode));
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
#endif
/* the server depends on the old, deprecated ldap_explode behavior which openldap
@@ -737,7 +755,16 @@ slapi_ldap_init_ext(
#if defined(USE_OPENLDAP)
if (ldapurl) {
+ if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
+ slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext",
+ "Could not perform internal ol_init init\n");
+ rc = -1;
+ goto done;
+ }
+
+ PR_Lock(ol_init_lock);
rc = ldap_initialize(&ld, ldapurl);
+ PR_Unlock(ol_init_lock);
if (rc) {
slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext",
"Could not initialize LDAP connection to [%s]: %d:%s\n",
@@ -751,7 +778,16 @@ slapi_ldap_init_ext(
} else { /* host port */
makeurl = convert_to_openldap_uri(hostname, port, (secure == 1 ? "ldaps" : "ldap"));
}
+ if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
+ slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext",
+ "Could not perform internal ol_init init\n");
+ rc = -1;
+ goto done;
+ }
+
+ PR_Lock(ol_init_lock);
rc = ldap_initialize(&ld, makeurl);
+ PR_Unlock(ol_init_lock);
if (rc) {
slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext",
"Could not initialize LDAP connection to [%s]: %d:%s\n",
diff --git a/ldap/servers/slapd/tools/ldclt/ldapfct.c b/ldap/servers/slapd/tools/ldclt/ldapfct.c
index 0e8a2fb..3f74fd0 100644
--- a/ldap/servers/slapd/tools/ldclt/ldapfct.c
+++ b/ldap/servers/slapd/tools/ldclt/ldapfct.c
@@ -708,6 +708,23 @@ done:
return rc;
}
+
+/* need mutex around ldap_initialize - see https://fedorahosted.org/389/ticket/348 */
+static PRCallOnceType ol_init_callOnce = {0,0};
+static PRLock *ol_init_lock = NULL;
+
+static PRStatus
+internal_ol_init_init(void)
+{
+ PR_ASSERT(NULL == ol_init_lock);
+ if ((ol_init_lock = PR_NewLock()) == NULL) {
+ PRErrorCode errorCode = PR_GetError();
+ printf("internal_ol_init_init PR_NewLock failed %d\n", errorCode);
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
#endif /* USE_OPENLDAP */
/* mctx is a global */
@@ -735,12 +752,20 @@ connectToLDAP(thread_context *tttctx, const char *bufBindDN, const char *bufPass
ldapurl = PR_smprintf("ldap%s://%s:%d/",
(mode & SSL) ? "s" : "",
mctx.hostname, mctx.port);
+ if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
+ printf("Could not perform internal ol_init init\n");
+ goto done;
+ }
+
+ PR_Lock(ol_init_lock);
if ((ret = ldap_initialize(&ld, ldapurl))) {
+ PR_Unlock(ol_init_lock);
printf ("ldclt[%d]: T%03d: Cannot ldap_initialize (%s), errno=%d ldaperror=%d:%s\n",
mctx.pid, thrdNum, ldapurl, errno, ret, my_ldap_err2string(ret));
fflush (stdout);
goto done;
}
+ PR_Unlock(ol_init_lock);
PR_smprintf_free(ldapurl);
ldapurl = NULL;
if (mode & SSL) {
diff --git a/ldap/servers/slapd/tools/rsearch/addthread.c b/ldap/servers/slapd/tools/rsearch/addthread.c
index f01ba18..a3e5568 100644
--- a/ldap/servers/slapd/tools/rsearch/addthread.c
+++ b/ldap/servers/slapd/tools/rsearch/addthread.c
@@ -176,6 +176,25 @@ static void at_disconnect(AddThread *at)
}
#endif
+#if defined(USE_OPENLDAP)
+/* need mutex around ldap_initialize - see https://fedorahosted.org/389/ticket/348 */
+static PRCallOnceType ol_init_callOnce = {0,0};
+static PRLock *ol_init_lock = NULL;
+
+static PRStatus
+internal_ol_init_init(void)
+{
+ PR_ASSERT(NULL == ol_init_lock);
+ if ((ol_init_lock = PR_NewLock()) == NULL) {
+ PRErrorCode errorCode = PR_GetError();
+ fprintf(stderr, "internal_ol_init_init PR_NewLock failed %d\n", errorCode);
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
+#endif
+
static void at_bind(AddThread *at)
{
int ret;
@@ -185,7 +204,14 @@ static void at_bind(AddThread *at)
at->ld = NULL;
ldapurl = PR_smprintf("ldap://%s:%d", hostname, port);
+ if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
+ fprintf(stderr, "Could not perform internal ol_init init\n");
+ return;
+ }
+
+ PR_Lock(ol_init_lock);
ret = ldap_initialize(&at->ld, ldapurl);
+ PR_Unlock(ol_init_lock);
PR_smprintf_free(ldapurl);
ldapurl = NULL;
if (ret) {
diff --git a/ldap/servers/slapd/tools/rsearch/searchthread.c b/ldap/servers/slapd/tools/rsearch/searchthread.c
index 9e2b0d6..8a74d58 100644
--- a/ldap/servers/slapd/tools/rsearch/searchthread.c
+++ b/ldap/servers/slapd/tools/rsearch/searchthread.c
@@ -180,6 +180,24 @@ static int st_bind_core(SearchThread *st, LDAP **ld, char *dn, char *pw)
return 1;
}
+#if defined(USE_OPENLDAP)
+/* need mutex around ldap_initialize - see https://fedorahosted.org/389/ticket/348 */
+static PRCallOnceType ol_init_callOnce = {0,0};
+static PRLock *ol_init_lock = NULL;
+
+static PRStatus
+internal_ol_init_init(void)
+{
+ PR_ASSERT(NULL == ol_init_lock);
+ if ((ol_init_lock = PR_NewLock()) == NULL) {
+ PRErrorCode errorCode = PR_GetError();
+ fprintf(stderr, "internal_ol_init_init PR_NewLock failed %d\n", errorCode);
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
+#endif
static int st_bind(SearchThread *st)
{
if (!st->ld) {
@@ -189,7 +207,14 @@ static int st_bind(SearchThread *st)
st->ld = NULL;
ldapurl = PR_smprintf("ldap://%s:%d", hostname, port);
+ if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
+ fprintf(stderr, "Could not perform internal ol_init init\n");
+ return 0;
+ }
+
+ PR_Lock(ol_init_lock);
ret = ldap_initialize(&st->ld, ldapurl);
+ PR_Unlock(ol_init_lock);
PR_smprintf_free(ldapurl);
ldapurl = NULL;
if (ret) {
@@ -212,7 +237,14 @@ static int st_bind(SearchThread *st)
st->ld2 = NULL;
ldapurl = PR_smprintf("ldap://%s:%d", hostname, port);
+ if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
+ fprintf(stderr, "Could not perform internal ol_init init\n");
+ return 0;
+ }
+
+ PR_Lock(ol_init_lock);
ret = ldap_initialize(&st->ld2, ldapurl);
+ PR_Unlock(ol_init_lock);
PR_smprintf_free(ldapurl);
ldapurl = NULL;
if (ret) {
11 years, 1 month
ldap/servers
by Mark Reynolds
ldap/servers/plugins/replication/repl5_agmt.c | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
New commits:
commit d4327cffcb79d2b4c46f4d31b4477e29a9ea0de0
Author: Mark Reynolds <mareynol(a)redhat.com>
Date: Fri Apr 27 13:53:31 2012 -0400
Ticket #214 - Adding Replication agreement should complain if required nsds5ReplicaCredentials not supplied
Bug Description: the server allows you to add replication agreements for SIMPLE & SASL/DIGEST-MD5 without
supplying a bind DN or password. The console enforces this, but not through the command line.
Fix Description: If the authentication method is not SSL Client Auth or SASL/GSSAPI, then make sure a
bind DN and password are supplied.
https://fedorahosted.org/389/ticket/214
Reviewed by: Noriko!
diff --git a/ldap/servers/plugins/replication/repl5_agmt.c b/ldap/servers/plugins/replication/repl5_agmt.c
index bfde962..cdd074e 100644
--- a/ldap/servers/plugins/replication/repl5_agmt.c
+++ b/ldap/servers/plugins/replication/repl5_agmt.c
@@ -219,6 +219,26 @@ agmt_is_valid(Repl_Agmt *ra)
slapi_sdn_get_dn(ra->dn), type_nsds5TransportInfo, type_nsds5ReplicaBindMethod);
return_value = 0;
}
+ /*
+ * If we are not using GSSAPI or SSL Client Auth, then a bind dn and password must be present
+ */
+ if(BINDMETHOD_SASL_GSSAPI != ra->bindmethod && BINDMETHOD_SSL_CLIENTAUTH != ra->bindmethod){
+ if(strcmp(ra->binddn,"") == 0 || ra->creds->bv_val == NULL){
+ char *auth_mech;
+
+ if(ra->bindmethod == BINDMETHOD_SIMPLE_AUTH){
+ auth_mech = "SIMPLE";
+ } else if (ra->bindmethod == BINDMETHOD_SASL_DIGEST_MD5){
+ auth_mech = "SASL/DIGEST-MD5";
+ } else {
+ auth_mech = "Unknown";
+ }
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Replication agreement \"%s\" "
+ "is malformed: a bind DN and password must be supplied for authentication "
+ "method \"%s\"\n", slapi_sdn_get_dn(ra->dn), auth_mech);
+ return_value = 0;
+ }
+ }
return return_value;
}
@@ -227,10 +247,9 @@ Repl_Agmt *
agmt_new_from_entry(Slapi_Entry *e)
{
Repl_Agmt *ra;
- char *tmpstr;
Slapi_Attr *sattr;
+ char *tmpstr;
char **denied_attrs = NULL;
-
char *auto_initialize = NULL;
char *val_nsds5BeginReplicaRefresh = "start";
11 years, 1 month
ldap/schema ldap/servers
by Mark Reynolds
ldap/schema/01core389.ldif | 1 +
ldap/servers/slapd/libglobs.c | 18 ++++++++++++++++++
ldap/servers/slapd/proto-slap.h | 1 +
ldap/servers/slapd/pw.c | 14 ++++++++++++++
ldap/servers/slapd/slap.h | 2 ++
5 files changed, 36 insertions(+)
New commits:
commit 540b2787be7090e727a174c0faaa0f1b28144295
Author: Mark Reynolds <mareynol(a)redhat.com>
Date: Fri Apr 27 12:31:44 2012 -0400
Ticket #207 - [RFE] enable attribute that tracks when a password was last set
Fix description: Added a new config setting to cn=config: passwordTrackUpdateTime
When this is set, we add an operational attribute: pwdUpdateTime
to the entry when we modify the userpassword.
https://fedorahosted.org/389/ticket/207
Reviewed by: Noriko!
diff --git a/ldap/schema/01core389.ldif b/ldap/schema/01core389.ldif
index ebd626f..b3df639 100644
--- a/ldap/schema/01core389.ldif
+++ b/ldap/schema/01core389.ldif
@@ -132,6 +132,7 @@ attributeTypes: ( 2.16.840.1.113730.3.1.2095 NAME 'connection' DESC 'Netscape de
attributeTypes: ( 2.16.840.1.113730.3.1.2096 NAME 'entryusn' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation X-ORIGIN 'Netscape' )
attributeTypes: ( 2.16.840.1.113730.3.1.2113 NAME 'internalModifiersName' DESC 'plugin dn' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation X-ORIGIN '389 Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.2114 NAME 'internalCreatorsName' DESC 'plugin dn' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation X-ORIGIN '389 Directory Server' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2133 NAME 'pwdUpdateTime' DESC 'Last password update time' SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 SINGLE-VALUE USAGE directoryOperation X-ORIGIN '389 Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.2111 NAME 'tombstoneNumSubordinates'
DESC 'count of immediate subordinates for tombstone entries'
EQUALITY integerMatch
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index d5b8faf..6d0db36 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -376,6 +376,9 @@ static struct config_get_and_set {
{CONFIG_PW_IS_LEGACY, config_set_pw_is_legacy_policy,
NULL, 0,
(void**)&global_slapdFrontendConfig.pw_policy.pw_is_legacy, CONFIG_ON_OFF, NULL},
+ {CONFIG_PW_TRACK_LAST_UPDATE_TIME, config_set_pw_track_last_update_time,
+ NULL, 0,
+ (void**)&global_slapdFrontendConfig.pw_policy.pw_track_update_time, CONFIG_ON_OFF, NULL},
{CONFIG_AUDITLOG_MAXNUMOFLOGSPERDIR_ATTRIBUTE, NULL,
log_set_numlogsperdir, SLAPD_AUDIT_LOG,
(void**)&global_slapdFrontendConfig.auditlog_maxnumlogs, CONFIG_INT, NULL},
@@ -1021,6 +1024,7 @@ FrontendConfig_init () {
cfg->pw_policy.pw_resetfailurecount = 600; /* 10 minutes */
cfg->pw_policy.pw_gracelimit = 0;
cfg->pw_policy.pw_is_legacy = LDAP_ON;
+ cfg->pw_policy.pw_track_update_time = LDAP_OFF;
cfg->pw_is_global_policy = LDAP_OFF;
cfg->accesslog_logging_enabled = LDAP_ON;
@@ -2435,6 +2439,20 @@ config_set_pw_is_legacy_policy( const char *attrname, char *value, char *errorbu
}
int
+config_set_pw_track_last_update_time( const char *attrname, char *value, char *errorbuf, int apply ) {
+ int retVal = LDAP_SUCCESS;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+ retVal = config_set_onoff ( attrname,
+ value,
+ &(slapdFrontendConfig->pw_policy.pw_track_update_time),
+ errorbuf,
+ apply);
+
+ return retVal;
+}
+
+int
config_set_pw_exp( const char *attrname, char *value, char *errorbuf, int apply ) {
int retVal = LDAP_SUCCESS;
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index d291be3..ea6f610 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -341,6 +341,7 @@ int config_set_pw_lockduration(const char *attrname, char *value, char *errorbu
int config_set_pw_resetfailurecount(const char *attrname, char *value, char *errorbuf, int apply );
int config_set_pw_is_global_policy(const char *attrname, char *value, char *errorbuf, int apply );
int config_set_pw_is_legacy_policy(const char *attrname, char *value, char *errorbuf, int apply );
+int config_set_pw_track_last_update_time(const char *attrname, char *value, char *errorbuf, int apply );
int config_set_pw_gracelimit(const char *attrname, char *value, char *errorbuf, int apply );
int config_set_useroc(const char *attrname, char *value, char *errorbuf, int apply );
int config_set_return_exact_case(const char *attrname, char *value, char *errorbuf, int apply );
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
index a6d6400..8cef61d 100644
--- a/ldap/servers/slapd/pw.c
+++ b/ldap/servers/slapd/pw.c
@@ -611,6 +611,13 @@ update_pw_info ( Slapi_PBlock *pb , char *old_pw) {
slapi_mods_init(&smods, 0);
+ /* Update the "pwdUpdateTime" attribute */
+ if ( pwpolicy->pw_track_update_time ){
+ timestr = format_genTime(cur_time);
+ slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "pwdUpdateTime",timestr);
+ slapi_ch_free((void **)×tr);
+ }
+
/* update password allow change time */
if ( pwpolicy->pw_minage != 0) {
timestr = format_genTime( time_plus_sec( cur_time,
@@ -1817,6 +1824,13 @@ new_passwdPolicy(Slapi_PBlock *pb, const char *dn)
pw_boolean_str2value(slapi_value_get_string(*sval));
}
}
+ else
+ if (!strcasecmp(attr_name, "passwordTrackUpdateTime")) {
+ if ((sval = attr_get_present_values(attr))) {
+ pwdpolicy->pw_track_update_time =
+ pw_boolean_str2value(slapi_value_get_string(*sval));
+ }
+ }
} /* end of for() loop */
if (pw_entry) {
slapi_entry_free(pw_entry);
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 54a921e..2e4db56 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1956,6 +1956,7 @@ typedef struct _slapdEntryPoints {
#define CONFIG_PW_ISGLOBAL_ATTRIBUTE "passwordIsGlobalPolicy"
#define CONFIG_PW_GRACELIMIT_ATTRIBUTE "passwordGraceLimit"
#define CONFIG_PW_IS_LEGACY "passwordLegacyPolicy"
+#define CONFIG_PW_TRACK_LAST_UPDATE_TIME "passwordTrackUpdateTime"
#define CONFIG_ACCESSLOG_BUFFERING_ATTRIBUTE "nsslapd-accesslog-logbuffering"
#define CONFIG_CSNLOGGING_ATTRIBUTE "nsslapd-csnlogging"
#define CONFIG_RETURN_EXACT_CASE_ATTRIBUTE "nsslapd-return-exact-case"
@@ -2044,6 +2045,7 @@ typedef struct passwordpolicyarray {
long pw_resetfailurecount;
int pw_gracelimit;
int pw_is_legacy;
+ int pw_track_update_time;
struct pw_scheme *pw_storagescheme;
} passwdPolicy;
11 years, 1 month
ldap/schema ldap/servers
by Mark Reynolds
ldap/schema/01core389.ldif | 3
ldap/servers/plugins/replication/cl5_api.c | 5 +
ldap/servers/plugins/replication/repl5.h | 3
ldap/servers/plugins/replication/repl5_agmt.c | 69 ++++++++++++++++
ldap/servers/plugins/replication/repl5_agmtlist.c | 13 ++-
ldap/servers/plugins/replication/repl5_replica.c | 14 +--
ldap/servers/plugins/replication/repl5_replica_config.c | 8 +
ldap/servers/plugins/replication/repl_extop.c | 8 +
ldap/servers/plugins/replication/repl_globals.c | 1
9 files changed, 115 insertions(+), 9 deletions(-)
New commits:
commit 7876d188934cfa05ba7dbbc9e8c60f79317a1018
Author: root <root(a)localhost.localdomain>
Date: Wed Apr 25 15:37:45 2012 -0400
Ticket #216 - RFE - Disable replication agreements
Bug Description: Allow replication agreements to be disabled.
Fix Description: Created a new repl agmt attribute: nsds5ReplicaEnabled
to control the agreement state.
https://fedorahosted.org/389/ticket/216
Reviewed by: Noriko!
diff --git a/ldap/schema/01core389.ldif b/ldap/schema/01core389.ldif
index f1e7543..ebd626f 100644
--- a/ldap/schema/01core389.ldif
+++ b/ldap/schema/01core389.ldif
@@ -100,6 +100,7 @@ attributeTypes: ( 2.16.840.1.113730.3.1.687 NAME 'nsds5replicaChangesSentSinceSt
attributeTypes: ( 2.16.840.1.113730.3.1.688 NAME 'nsds5replicaLastUpdateStatus' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE NO-USER-MODIFICATION X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.689 NAME 'nsds5replicaUpdateInProgress' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE NO-USER-MODIFICATION X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.802 NAME 'nsds5ReplicaLegacyConsumer' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2132 NAME 'nsds5ReplicaEnabled' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.804 NAME 'nsSchemaCSN' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE USAGE directoryOperation X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.805 NAME 'nsds5replicaTimeout' DESC 'Netscape defined attribute type' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.807 NAME 'nsds5replicaLastInitStart' DESC 'Netscape defined attribute type' EQUALITY generalizedTimeMatch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 SINGLE-VALUE NO-USER-MODIFICATION X-ORIGIN 'Netscape Directory Server' )
@@ -151,7 +152,7 @@ objectClasses: ( 2.16.840.1.113730.3.2.110 NAME 'nsMappingTree' DESC 'Netscape d
objectClasses: ( 2.16.840.1.113730.3.2.104 NAME 'nsContainer' DESC 'Netscape defined objectclass' SUP top MUST ( CN ) X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.108 NAME 'nsDS5Replica' DESC 'Netscape defined objectclass' SUP top MUST ( nsDS5ReplicaRoot $ nsDS5ReplicaId ) MAY (cn $ nsDS5ReplicaType $ nsDS5ReplicaBindDN $ nsState $ nsDS5ReplicaName $ nsDS5Flags $ nsDS5Task $ nsDS5ReplicaReferral $ nsDS5ReplicaAutoReferral $ nsds5ReplicaPurgeDelay $ nsds5ReplicaTombstonePurgeInterval $ nsds5ReplicaChangeCount $ nsds5ReplicaLegacyConsumer) X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.113 NAME 'nsTombstone' DESC 'Netscape defined objectclass' SUP top MAY ( nsParentUniqueId $ nscpEntryDN ) X-ORIGIN 'Netscape Directory Server' )
-objectClasses: ( 2.16.840.1.113730.3.2.103 NAME 'nsDS5ReplicationAgreement' DESC 'Netscape defined objectclass' SUP top MUST ( cn ) MAY ( nsDS5ReplicaHost $ nsDS5ReplicaPort $ nsDS5ReplicaTransportInfo $ nsDS5ReplicaBindDN $ nsDS5ReplicaCredentials $ nsDS5ReplicaBindMethod $ nsDS5ReplicaRoot $ nsDS5ReplicatedAttributeList $ nsDS5ReplicatedAttributeListTotal $ nsDS5ReplicaUpdateSchedule $ nsds5BeginReplicaRefresh $ description $ nsds50ruv $ nsruvReplicaLastModified $ nsds5ReplicaTimeout $ nsds5replicaChangesSentSinceStartup $ nsds5replicaLastUpdateEnd $ nsds5replicaLastUpdateStart $ nsds5replicaLastUpdateStatus $ nsds5replicaUpdateInProgress $ nsds5replicaLastInitEnd $ nsds5replicaLastInitStart $ nsds5replicaLastInitStatus $ nsds5debugreplicatimeout $ nsds5replicaBusyWaitTime $ nsds5replicaSessionPauseTime ) X-ORIGIN 'Netscape Directory Server' )
+objectClasses: ( 2.16.840.1.113730.3.2.103 NAME 'nsDS5ReplicationAgreement' DESC 'Netscape defined objectclass' SUP top MUST ( cn ) MAY ( nsDS5ReplicaHost $ nsDS5ReplicaPort $ nsDS5ReplicaTransportInfo $ nsDS5ReplicaBindDN $ nsDS5ReplicaCredentials $ nsDS5ReplicaBindMethod $ nsDS5ReplicaRoot $ nsDS5ReplicatedAttributeList $ nsDS5ReplicatedAttributeListTotal $ nsDS5ReplicaUpdateSchedule $ nsds5BeginReplicaRefresh $ description $ nsds50ruv $ nsruvReplicaLastModified $ nsds5ReplicaTimeout $ nsds5replicaChangesSentSinceStartup $ nsds5replicaLastUpdateEnd $ nsds5replicaLastUpdateStart $ nsds5replicaLastUpdateStatus $ nsds5replicaUpdateInProgress $ nsds5replicaLastInitEnd $ nsds5ReplicaEnabled $ nsds5replicaLastInitStart $ nsds5replicaLastInitStatus $ nsds5debugreplicatimeout $ nsds5replicaBusyWaitTime $ nsds5replicaSessionPauseTime ) X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.39 NAME 'nsslapdConfig' DESC 'Netscape defined objectclass' SUP top MAY ( cn ) X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.317 NAME 'nsSaslMapping' DESC 'Netscape defined objectclass' SUP top MUST ( cn $ nsSaslMapRegexString $ nsSaslMapBaseDNTemplate $ nsSaslMapFilterTemplate ) X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.43 NAME 'nsSNMP' DESC 'Netscape defined objectclass' SUP top MUST ( cn $ nsSNMPEnabled ) MAY ( nsSNMPOrganization $ nsSNMPLocation $ nsSNMPContact $ nsSNMPDescription $ nsSNMPName $ nsSNMPMasterHost $ nsSNMPMasterPort ) X-ORIGIN 'Netscape Directory Server' )
diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c
index 03d50ca..4c23af5 100644
--- a/ldap/servers/plugins/replication/cl5_api.c
+++ b/ldap/servers/plugins/replication/cl5_api.c
@@ -3998,6 +3998,11 @@ static int _cl5GetRUV2Purge2 (Object *fileObj, RUV **ruv)
agmt = (Repl_Agmt*)object_get_data (agmtObj);
PR_ASSERT (agmt);
+ if(!agmt_is_enabled(agmt)){
+ agmtObj = agmtlist_get_next_agreement_for_replica(r, agmtObj);
+ continue;
+ }
+
consRUVObj = agmt_get_consumer_ruv (agmt);
if (consRUVObj)
{
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index e315150..23d9753 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -155,6 +155,7 @@ extern const char *type_nsds5ReplicaInitialize;
extern const char *type_nsds5ReplicaTimeout;
extern const char *type_nsds5ReplicaBusyWaitTime;
extern const char *type_nsds5ReplicaSessionPauseTime;
+extern const char *type_nsds5ReplicaEnabled;
/* Attribute names for windows replication agreements */
extern const char *type_nsds7WindowsReplicaArea;
@@ -353,6 +354,8 @@ void agmt_set_priv (Repl_Agmt *agmt, void* priv);
int get_agmt_agreement_type ( Repl_Agmt *agmt);
void* agmt_get_connection( Repl_Agmt *ra);
int agmt_has_protocol(Repl_Agmt *agmt);
+PRBool agmt_is_enabled(Repl_Agmt *ra);
+int agmt_set_enabled_from_entry(Repl_Agmt *ra, Slapi_Entry *e);
typedef struct replica Replica;
diff --git a/ldap/servers/plugins/replication/repl5_agmt.c b/ldap/servers/plugins/replication/repl5_agmt.c
index 8714021..bfde962 100644
--- a/ldap/servers/plugins/replication/repl5_agmt.c
+++ b/ldap/servers/plugins/replication/repl5_agmt.c
@@ -117,6 +117,7 @@ typedef struct repl5agmt {
time_t last_update_end_time; /* Local end time of last update session */
char last_update_status[STATUS_LEN]; /* Status of last update. Format = numeric code <space> textual description */
PRBool update_in_progress;
+ PRBool is_enabled;
time_t last_init_start_time; /* Local start time of last total init */
time_t last_init_end_time; /* Local end time of last total init */
char last_init_status[STATUS_LEN]; /* Status of last total init. Format = numeric code <space> textual description */
@@ -317,6 +318,19 @@ agmt_new_from_entry(Slapi_Entry *e)
ra->replarea = slapi_sdn_new_dn_passin(tmpstr);
}
+ /* Replica enabled */
+ tmpstr = slapi_entry_attr_get_charptr(e, type_nsds5ReplicaEnabled);
+ if (NULL != tmpstr)
+ {
+ if(strcasecmp(tmpstr, "on") == 0){
+ ra->is_enabled = PR_TRUE;
+ } else {
+ ra->is_enabled = PR_FALSE;
+ }
+ } else {
+ ra->is_enabled = PR_TRUE;
+ }
+
/* Replication schedule */
ra->schedule = schedule_new(update_window_state_change_callback, ra, agmt_get_long_name(ra));
if (slapi_entry_attr_find(e, type_nsds5ReplicaUpdateSchedule, &sattr) == 0)
@@ -2442,3 +2456,58 @@ agmt_has_protocol(Repl_Agmt *agmt)
}
return 0;
}
+
+PRBool
+agmt_is_enabled(Repl_Agmt *ra)
+{
+ PRBool state;
+ PR_Lock(ra->lock);
+ state = ra->is_enabled;
+ PR_Unlock(ra->lock);
+
+ return state;
+}
+
+int
+agmt_set_enabled_from_entry(Repl_Agmt *ra, Slapi_Entry *e){
+ char *attr_val = NULL;
+ int rc = 0;
+
+ if(ra == NULL){
+ return -1;
+ }
+
+ PR_Lock(ra->lock);
+ attr_val = slapi_entry_attr_get_charptr(e, type_nsds5ReplicaEnabled);
+ if(attr_val){
+ if(strcasecmp(attr_val,"on") == 0){
+ if(!ra->is_enabled){
+ ra->is_enabled = PR_TRUE;
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmt_set_enabled_from_entry: "
+ "agreement is now enabled (%s)\n",ra->long_name);
+ PR_Unlock(ra->lock);
+ agmt_start(ra);
+ slapi_ch_free_string(&attr_val);
+ return rc;
+ }
+ } else {
+ if(ra->is_enabled){
+ ra->is_enabled = PR_FALSE;
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmt_set_enabled_from_entry: "
+ "agreement is now disabled (%s)\n",ra->long_name);
+ PR_Unlock(ra->lock);
+ agmt_stop(ra);
+ agmt_update_consumer_ruv(ra);
+ agmt_set_last_update_status(ra,0,0,"agreement disabled");
+ slapi_ch_free_string(&attr_val);
+ return rc;
+ }
+ }
+ } else {
+ rc = -1;
+ }
+ PR_Unlock(ra->lock);
+
+ return rc;
+}
+
diff --git a/ldap/servers/plugins/replication/repl5_agmtlist.c b/ldap/servers/plugins/replication/repl5_agmtlist.c
index 8a98c21..1c18a85 100644
--- a/ldap/servers/plugins/replication/repl5_agmtlist.c
+++ b/ldap/servers/plugins/replication/repl5_agmtlist.c
@@ -154,7 +154,9 @@ add_new_agreement(Slapi_Entry *e)
Object *repl_obj = NULL;
Object *ro = NULL;
- if (ra == NULL) return 1; /* tell search result handler callback this entry was not sent */
+ /* tell search result handler callback this entry was not sent */
+ if (ra == NULL)
+ return 1;
ro = object_new((void *)ra, agmt_delete);
objset_add_obj(agmt_set, ro);
@@ -488,6 +490,15 @@ agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry
/* ignore modifier's name and timestamp attributes and the description. */
continue;
}
+ else if (slapi_attr_types_equivalent(mods[i]->mod_type, type_nsds5ReplicaEnabled))
+ {
+ if(agmt_set_enabled_from_entry(agmt, e) != 0){
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: "
+ "failed to set replica agmt state \"enabled/disabled\" for %s\n",agmt_get_long_name(agmt));
+ *returncode = LDAP_OPERATIONS_ERROR;
+ rc = SLAPI_DSE_CALLBACK_ERROR;
+ }
+ }
else if (0 == windows_handle_modify_agreement(agmt, mods[i]->mod_type, e))
{
slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: "
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
index c2e69f8..6434dbd 100644
--- a/ldap/servers/plugins/replication/repl5_replica.c
+++ b/ldap/servers/plugins/replication/repl5_replica.c
@@ -3445,12 +3445,12 @@ start_agreements_for_replica (Replica *r, PRBool start)
{
agmt = (Repl_Agmt*)object_get_data (agmt_obj);
PR_ASSERT (agmt);
-
- if (start)
- agmt_start (agmt);
- else /* stop */
- agmt_stop (agmt);
-
+ if(agmt_is_enabled(agmt)){
+ if (start)
+ agmt_start (agmt);
+ else /* stop */
+ agmt_stop (agmt);
+ }
agmt_obj = agmtlist_get_next_agreement_for_replica (r, agmt_obj);
}
}
@@ -3463,7 +3463,7 @@ int replica_start_agreement(Replica *r, Repl_Agmt *ra)
PR_Lock(r->agmt_lock);
- if (!replica_is_state_flag_set(r, REPLICA_AGREEMENTS_DISABLED)) {
+ if (!replica_is_state_flag_set(r, REPLICA_AGREEMENTS_DISABLED) && agmt_is_enabled(ra)) {
ret = agmt_start(ra); /* Start the replication agreement */
}
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index 78a948b..5a3ed07 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -1218,6 +1218,10 @@ replica_execute_cleanall_ruv_task (Object *r, ReplicaId rid, char *returntext)
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;
+ }
dn = agmt_get_dn_byref(agmt);
conn = (Repl_Connection *)agmt_get_connection(agmt);
if(conn == NULL){
@@ -1311,6 +1315,10 @@ replica_execute_release_ruv_task(Object *r, ReplicaId rid, char *returntext)
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;
+ }
dn = agmt_get_dn_byref(agmt);
conn = (Repl_Connection *)agmt_get_connection(agmt);
if(conn == NULL){
diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c
index 7e2ebbd..31a9ad0 100644
--- a/ldap/servers/plugins/replication/repl_extop.c
+++ b/ldap/servers/plugins/replication/repl_extop.c
@@ -1458,6 +1458,10 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb){
while (agmt_obj)
{
agmt = (Repl_Agmt*)object_get_data (agmt_obj);
+ if(!agmt_is_enabled(agmt)){
+ agmt_obj = agmtlist_get_next_agreement_for_replica (r, agmt_obj);
+ continue;
+ }
dn = agmt_get_dn_byref(agmt);
conn = (Repl_Connection *)agmt_get_connection(agmt);
if(conn == NULL){
@@ -1594,6 +1598,10 @@ multimaster_extop_releaseruv(Slapi_PBlock *pb){
while (agmt_obj)
{
agmt = (Repl_Agmt*)object_get_data (agmt_obj);
+ if(!agmt_is_enabled(agmt)){
+ agmt_obj = agmtlist_get_next_agreement_for_replica (r, agmt_obj);
+ continue;
+ }
dn = agmt_get_dn_byref(agmt);
conn = (Repl_Connection *)agmt_get_connection(agmt);
if(conn == NULL){
diff --git a/ldap/servers/plugins/replication/repl_globals.c b/ldap/servers/plugins/replication/repl_globals.c
index f0aea12..d2d2318 100644
--- a/ldap/servers/plugins/replication/repl_globals.c
+++ b/ldap/servers/plugins/replication/repl_globals.c
@@ -126,6 +126,7 @@ const char *type_nsds5ReplicaInitialize = "nsds5BeginReplicaRefresh";
const char *type_nsds5ReplicaTimeout = "nsds5ReplicaTimeout";
const char *type_nsds5ReplicaBusyWaitTime = "nsds5ReplicaBusyWaitTime";
const char *type_nsds5ReplicaSessionPauseTime = "nsds5ReplicaSessionPauseTime";
+const char *type_nsds5ReplicaEnabled = "nsds5ReplicaEnabled";
/* windows sync specific attributes */
const char *type_nsds7WindowsReplicaArea = "nsds7WindowsReplicaSubtree";
11 years, 1 month
ldap/servers
by Mark Reynolds
ldap/servers/plugins/replication/cl5_api.c | 104 ++++
ldap/servers/plugins/replication/cl5_api.h | 4
ldap/servers/plugins/replication/repl5.h | 18
ldap/servers/plugins/replication/repl5_agmt.c | 9
ldap/servers/plugins/replication/repl5_init.c | 63 ++
ldap/servers/plugins/replication/repl5_plugins.c | 10
ldap/servers/plugins/replication/repl5_replica_config.c | 344 +++++++++++++++-
ldap/servers/plugins/replication/repl5_ruv.c | 33 +
ldap/servers/plugins/replication/repl_extop.c | 341 +++++++++++++++
9 files changed, 897 insertions(+), 29 deletions(-)
New commits:
commit 0f50544b9567907edd0ba645951d7cd325354107
Author: root <root(a)localhost.localdomain>
Date: Mon Apr 23 13:36:04 2012 -0400
Ticket #337 - RFE - Improve CLEANRUV functionality
Bug Description: Previously the steps to remove a replica and its RUV was problematic.
I created two new "tasks" to take care of the entire replication environment.
Fix Description:
[1] The new task "CLEANALLRUV<rid>" - run it once on any master
This marks the rid as invalid. Used to reject updates to the changelog, and the database RUV
It then sends a "CLEANRUV" extended operation to each agreement.
Then it cleans its own RUV.
The CLEANRUV extended op then triggers that replica to send the the same CLEANRUV extop to its replicas, then it cleans its own RID. Basically
this operation cascades through the entire replication environment.
[2] The "RELEASERUV<rid>" task - run it once on any master
Once the RUV's have been cleaned on all the replicas, you need to "release" the rid so that it can be reused. This operation also cascades thro
ugh the entire replication environment. This also triggers changelog trimming.
For all of this to work correctly, there is a list of steps that needs to be followed. This procedure is attached to the ticket.
https://fedorahosted.org/389/ticket/337
reviewed by: ?
diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c
index 2b57f91..03d50ca 100644
--- a/ldap/servers/plugins/replication/cl5_api.c
+++ b/ldap/servers/plugins/replication/cl5_api.c
@@ -355,6 +355,7 @@ static int _cl5WriteRUV (CL5DBFile *file, PRBool purge);
static int _cl5ConstructRUV (const char *replGen, Object *obj, PRBool purge);
static int _cl5UpdateRUV (Object *obj, CSN *csn, PRBool newReplica, PRBool purge);
static int _cl5GetRUV2Purge2 (Object *fileObj, RUV **ruv);
+void trigger_cl_trimming_thread();
/* bakup/recovery, import/export */
static int _cl5LDIF2Operation (char *ldifEntry, slapi_operation_parameters *op,
@@ -3477,6 +3478,7 @@ static void _cl5TrimFile (Object *obj, long *numToTrim)
count = 0;
txnid = NULL;
abort = PR_FALSE;
+ ReplicaId rid;
/* DB txn lock accessed pages until the end of the transaction. */
@@ -3497,13 +3499,14 @@ static void _cl5TrimFile (Object *obj, long *numToTrim)
* This change can be trimmed if it exceeds purge
* parameters and has been seen by all consumers.
*/
+ rid = csn_get_replicaid (op.csn);
if ( (*numToTrim > 0 || _cl5CanTrim (entry.time, numToTrim)) &&
ruv_covers_csn_strict (ruv, op.csn) )
- {
+ {
rc = _cl5CurrentDeleteEntry (it);
- if ( rc == CL5_SUCCESS )
+ if ( rc == CL5_SUCCESS && !is_released_rid(rid))
{
- /* update purge vector */
+ /* update purge vector, unless this is a released rid */
rc = _cl5UpdateRUV (obj, op.csn, PR_FALSE, PR_TRUE);
}
if ( rc == CL5_SUCCESS)
@@ -3529,8 +3532,6 @@ static void _cl5TrimFile (Object *obj, long *numToTrim)
* the trim forever.
*/
CSN *maxcsn = NULL;
- ReplicaId rid;
-
rid = csn_get_replicaid (op.csn);
ruv_get_largest_csn_for_replica (ruv, rid, &maxcsn);
if ( csn_compare (op.csn, maxcsn) != 0 )
@@ -3620,10 +3621,10 @@ static PRBool _cl5CanTrim (time_t time, long *numToTrim)
*numToTrim = cl5GetOperationCount (NULL) - s_cl5Desc.dbTrim.maxEntries;
return ( *numToTrim > 0 );
}
-
+
if (s_cl5Desc.dbTrim.maxEntries > 0 &&
(*numToTrim = cl5GetOperationCount (NULL) - s_cl5Desc.dbTrim.maxEntries) > 0)
- return PR_TRUE;
+ return PR_TRUE;
if (time)
return (current_time () - time > s_cl5Desc.dbTrim.maxAge);
@@ -3805,6 +3806,7 @@ static int _cl5ConstructRUV (const char *replGen, Object *obj, PRBool purge)
void *iterator = NULL;
slapi_operation_parameters op = {0};
CL5DBFile *file;
+ ReplicaId rid;
PR_ASSERT (replGen && obj);
@@ -3828,6 +3830,15 @@ static int _cl5ConstructRUV (const char *replGen, Object *obj, PRBool purge)
rc = _cl5GetFirstEntry (obj, &entry, &iterator, NULL);
while (rc == CL5_SUCCESS)
{
+ rid = csn_get_replicaid (op.csn);
+ if(is_cleaned_rid(rid)){
+ /* skip this entry as the rid is invalid */
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, "_cl5ConstructRUV: "
+ "skipping entry because its csn contains a cleaned rid(%d)\n", rid);
+ cl5_operation_parameters_done (&op);
+ rc = _cl5GetNextEntry (&entry, iterator);
+ continue;
+ }
if (purge)
rc = ruv_set_csns_keep_smallest(file->purgeRUV, op.csn);
else
@@ -3876,28 +3887,32 @@ static int _cl5UpdateRUV (Object *obj, CSN *csn, PRBool newReplica, PRBool purge
file = (CL5DBFile*)object_get_data (obj);
- /* if purge is TRUE, file->purgeRUV must be set;
- if purge is FALSE, maxRUV must be set */
+ /*
+ * if purge is TRUE, file->purgeRUV must be set;
+ * if purge is FALSE, maxRUV must be set
+ */
PR_ASSERT (file && ((purge && file->purgeRUV) || (!purge && file->maxRUV)));
+ rid = csn_get_replicaid(csn);
/* update vector only if this replica is not yet part of RUV */
if (purge && newReplica)
{
- rid = csn_get_replicaid(csn);
if (ruv_contains_replica (file->purgeRUV, rid))
return CL5_SUCCESS;
- else
+ else if(is_cleaned_rid(rid))
{
- /* if the replica is not part of the purgeRUV yet, add it */
- ruv_add_replica (file->purgeRUV, rid, multimaster_get_local_purl());
+ /* if the replica is not part of the purgeRUV yet, add it unless it's from a cleaned rid */
+ ruv_add_replica (file->purgeRUV, rid, multimaster_get_local_purl());
}
}
else
{
if (purge)
rc = ruv_set_csns(file->purgeRUV, csn, NULL);
- else
- rc = ruv_set_csns(file->maxRUV, csn, NULL);
+ else if(is_cleaned_rid(rid)){
+ /* don't update maxRuv is if rid is cleaned */
+ rc = ruv_set_csns(file->maxRUV, csn, NULL);
+ }
}
if (rc != RUV_SUCCESS)
@@ -4502,9 +4517,17 @@ static int _cl5WriteOperationTxn(const char *replName, const char *replGen,
CL5Entry entry;
CL5DBFile *file = NULL;
Object *file_obj = NULL;
+ ReplicaId rid = csn_get_replicaid (op->csn);
DB_TXN *txnid = NULL;
DB_TXN *parent_txnid = (DB_TXN *)txn;
+ /*
+ * If the op csn contains the cleaned rid, don't write it
+ */
+ if(is_cleaned_rid(rid)){
+ return CL5_SUCCESS;
+ }
+
rc = _cl5GetDBFileByReplicaName (replName, replGen, &file_obj);
if (rc == CL5_NOTFOUND)
{
@@ -4770,7 +4793,7 @@ static int _cl5GetFirstEntry (Object *obj, CL5Entry *entry, void **iterator, DB_
rc, db_strerror(rc));
rc = CL5_DB_ERROR;
-done:;
+done:
/* error occured */
/* We didn't success in assigning this cursor to the iterator,
* so we need to free the cursor here */
@@ -6512,3 +6535,52 @@ bail:
changelog5_config_done(&config);
return rc;
}
+
+/*
+ * Clean the in memory RUV, at shutdown we will write the update to the db
+ */
+void
+cl5CleanRUV(ReplicaId rid){
+ CL5DBFile *file;
+ Object *obj;
+
+ obj = objset_first_obj(s_cl5Desc.dbFiles);
+ while (obj){
+ file = (CL5DBFile *)object_get_data(obj);
+ ruv_delete_replica(file->purgeRUV, rid);
+ ruv_delete_replica(file->maxRUV, rid);
+ obj = objset_next_obj(s_cl5Desc.dbFiles, obj);
+ }
+
+ if (obj)
+ object_release (obj);
+}
+
+void trigger_cl_trimming(){
+ PRThread *trim_tid = NULL;
+ ReplicaId rid = get_released_rid();
+
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, "trigger_cl_trimming: rid (%d)\n",(int)rid);
+ trim_tid = PR_CreateThread(PR_USER_THREAD, (VFP)(void*)trigger_cl_trimming_thread,
+ NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD, DEFAULT_THREAD_STACKSIZE);
+ if (NULL == trim_tid){
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl,
+ "trigger_cl_trimming: failed to create trimming "
+ "thread; NSPR error - %d\n", PR_GetError ());
+ } else {
+ /* need a little time for the thread to get started */
+ DS_Sleep(PR_SecondsToInterval(1));
+ }
+}
+
+void
+trigger_cl_trimming_thread(){
+ /* make sure we have a change log, and we aren't closing it */
+ if(s_cl5Desc.dbState == CL5_STATE_CLOSED || s_cl5Desc.dbState == CL5_STATE_CLOSING){
+ return;
+ }
+ _cl5AddThread();
+ _cl5DoTrimming();
+ _cl5RemoveThread();
+}
diff --git a/ldap/servers/plugins/replication/cl5_api.h b/ldap/servers/plugins/replication/cl5_api.h
index 6f2552f..b9c3dd8 100644
--- a/ldap/servers/plugins/replication/cl5_api.h
+++ b/ldap/servers/plugins/replication/cl5_api.h
@@ -487,4 +487,8 @@ int cl5WriteRUV();
Return: TRUE
*/
int cl5DeleteRUV();
+void cl5CleanRUV(ReplicaId rid);
+void cl5NotifyCleanup(int rid);
+void trigger_cl_trimming();
+
#endif
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index ac2cd88..e315150 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -94,6 +94,9 @@
* new set of start and response extops. */
#define REPL_START_NSDS90_REPLICATION_REQUEST_OID "2.16.840.1.113730.3.5.12"
#define REPL_NSDS90_REPLICATION_RESPONSE_OID "2.16.840.1.113730.3.5.13"
+/* cleanruv/releaseruv extended ops */
+#define REPL_CLEANRUV_OID "2.16.840.1.113730.3.6.5"
+#define REPL_RELEASERUV_OID "2.16.840.1.113730.3.6.6"
/* DS 5.0 replication protocol error codes */
@@ -218,6 +221,8 @@ char* get_repl_session_id (Slapi_PBlock *pb, char *id, CSN **opcsn);
/* In repl_extop.c */
int multimaster_extop_StartNSDS50ReplicationRequest(Slapi_PBlock *pb);
int multimaster_extop_EndNSDS50ReplicationRequest(Slapi_PBlock *pb);
+int multimaster_extop_cleanruv(Slapi_PBlock *pb);
+int multimaster_extop_releaseruv(Slapi_PBlock *pb);
int extop_noop(Slapi_PBlock *pb);
struct berval *NSDS50StartReplicationRequest_new(const char *protocol_oid,
const char *repl_root, char **extra_referrals, CSN *csn);
@@ -345,8 +350,8 @@ char **agmt_get_fractional_attrs_total(const Repl_Agmt *ra);
char **agmt_validate_replicated_attributes(Repl_Agmt *ra, int total);
void* agmt_get_priv (const Repl_Agmt *agmt);
void agmt_set_priv (Repl_Agmt *agmt, void* priv);
-
int get_agmt_agreement_type ( Repl_Agmt *agmt);
+void* agmt_get_connection( Repl_Agmt *ra);
int agmt_has_protocol(Repl_Agmt *agmt);
typedef struct replica Replica;
@@ -579,6 +584,17 @@ void multimaster_be_state_change (void *handle, char *be_name, int old_be_state,
int replica_config_init();
void replica_config_destroy ();
int get_replica_type(Replica *r);
+int replica_execute_cleanruv_task_ext(Object *r, ReplicaId rid);
+void set_cleaned_rid(ReplicaId rid);
+void delete_cleaned_rid();
+int is_cleaned_rid(ReplicaId rid);
+int get_released_rid();
+void set_released_rid(int rid);
+int is_released_rid(int rid);
+int is_already_released_rid();
+void delete_released_rid();
+
+#define ALREADY_RELEASED -1
/* replutil.c */
LDAPControl* create_managedsait_control ();
diff --git a/ldap/servers/plugins/replication/repl5_agmt.c b/ldap/servers/plugins/replication/repl5_agmt.c
index 1d9affa..8714021 100644
--- a/ldap/servers/plugins/replication/repl5_agmt.c
+++ b/ldap/servers/plugins/replication/repl5_agmt.c
@@ -2425,6 +2425,15 @@ ReplicaId agmt_get_consumerRID(Repl_Agmt *ra)
return ra->consumerRID;
}
+void* agmt_get_connection(Repl_Agmt *ra)
+{
+ if(ra->protocol){
+ return (void *)prot_get_connection(ra->protocol);
+ } else {
+ return NULL;
+ }
+}
+
int
agmt_has_protocol(Repl_Agmt *agmt)
{
diff --git a/ldap/servers/plugins/replication/repl5_init.c b/ldap/servers/plugins/replication/repl5_init.c
index 4e2464c..a878b19 100644
--- a/ldap/servers/plugins/replication/repl5_init.c
+++ b/ldap/servers/plugins/replication/repl5_init.c
@@ -118,6 +118,22 @@ static char *response_name_list[] = {
NSDS_REPL_NAME_PREFIX " Response",
NULL
};
+static char *cleanruv_oid_list[] = {
+ REPL_CLEANRUV_OID,
+ NULL
+};
+static char *cleanruv_name_list[] = {
+ NSDS_REPL_NAME_PREFIX " Cleanruv",
+ NULL
+};
+static char *releaseruv_oid_list[] = {
+ REPL_RELEASERUV_OID,
+ NULL
+};
+static char *releaseruv_name_list[] = {
+ NSDS_REPL_NAME_PREFIX " Releaseruv",
+ NULL
+};
/* List of plugin identities for every plugin registered. Plugin identity
is passed by the server in the plugin init function and must be supplied
@@ -434,6 +450,51 @@ multimaster_response_extop_init( Slapi_PBlock *pb )
return rc;
}
+int
+multimaster_cleanruv_extop_init( Slapi_PBlock *pb )
+{
+ int rc= 0; /* OK */
+ void *identity = NULL;
+
+ /* get plugin identity and store it to pass to internal operations */
+ slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &identity);
+ PR_ASSERT (identity);
+
+ if (slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 ) != 0 ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&multimasterextopdesc ) != 0 ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_EXT_OP_OIDLIST, (void *)cleanruv_oid_list ) != 0 ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_EXT_OP_NAMELIST, (void *)cleanruv_name_list ) != 0 ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_EXT_OP_FN, (void *)multimaster_extop_cleanruv ))
+ {
+ slapi_log_error( SLAPI_LOG_PLUGIN, repl_plugin_name, "multimaster_cleanruv_extop_init failed\n" );
+ rc= -1;
+ }
+
+ return rc;
+}
+
+int
+multimaster_releaseruv_extop_init( Slapi_PBlock *pb )
+{
+ int rc= 0; /* OK */
+ void *identity = NULL;
+
+ /* get plugin identity and store it to pass to internal operations */
+ slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &identity);
+ PR_ASSERT (identity);
+
+ if (slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 ) != 0 ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&multimasterextopdesc ) != 0 ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_EXT_OP_OIDLIST, (void *)releaseruv_oid_list ) != 0 ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_EXT_OP_NAMELIST, (void *)releaseruv_name_list ) != 0 ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_EXT_OP_FN, (void *)multimaster_extop_releaseruv ))
+ {
+ slapi_log_error( SLAPI_LOG_PLUGIN, repl_plugin_name, "multimaster_releaseruv_extop_init failed\n" );
+ rc= -1;
+ }
+
+ return rc;
+}
static PRBool
check_for_ldif_dump(Slapi_PBlock *pb)
@@ -618,6 +679,8 @@ int replication_multimaster_plugin_init(Slapi_PBlock *pb)
rc= slapi_register_plugin("extendedop", 1 /* Enabled */, "multimaster_end_extop_init", multimaster_end_extop_init, "Multimaster replication end extended operation plugin", NULL, identity);
rc= slapi_register_plugin("extendedop", 1 /* Enabled */, "multimaster_total_extop_init", multimaster_total_extop_init, "Multimaster replication total update extended operation plugin", NULL, identity);
rc= slapi_register_plugin("extendedop", 1 /* Enabled */, "multimaster_response_extop_init", multimaster_response_extop_init, "Multimaster replication extended response plugin", NULL, identity);
+ rc= slapi_register_plugin("extendedop", 1 /* Enabled */, "multimaster_cleanruv_extop_init", multimaster_cleanruv_extop_init, "Multimaster replication cleanruv extended operation plugin", NULL, identity);
+ rc= slapi_register_plugin("extendedop", 1 /* Enabled */, "multimaster_releaseruv_extop_init", multimaster_releaseruv_extop_init, "Multimaster replication releaserid extended response plugin", NULL, identity);
if (0 == rc)
{
multimaster_initialised = 1;
diff --git a/ldap/servers/plugins/replication/repl5_plugins.c b/ldap/servers/plugins/replication/repl5_plugins.c
index c806c08..dfbb80e 100644
--- a/ldap/servers/plugins/replication/repl5_plugins.c
+++ b/ldap/servers/plugins/replication/repl5_plugins.c
@@ -1005,6 +1005,15 @@ write_changelog_and_ruv (Slapi_PBlock *pb)
r = (Replica*)object_get_data (repl_obj);
PR_ASSERT (r);
+ /*
+ * In case we had to run cleanruv, we don't want to continue to write
+ * updates to the changelog/database ruv from that replica(rid).
+ */
+ if( is_cleaned_rid(replica_get_rid(r))){
+ /* this RID has been cleaned, just goto done */
+ goto done;
+ }
+
if (replica_is_flag_set (r, REPLICA_LOG_CHANGES) &&
(cl5GetState () == CL5_STATE_OPEN))
{
@@ -1111,6 +1120,7 @@ write_changelog_and_ruv (Slapi_PBlock *pb)
update_ruv_component(r, opcsn, pb);
}
+done:
object_release (repl_obj);
return return_value;
}
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index 94f4179..78a948b 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -56,9 +56,15 @@
#define LDIF2CL_TASK "LDIF2CL"
#define CLEANRUV "CLEANRUV"
#define CLEANRUVLEN 8
+#define CLEANALLRUV "CLEANALLRUV"
+#define CLEANALLRUVLEN 11
+#define RELEASERUV "RELEASERUV"
+#define RELEASERUVLEN 10
#define REPLICA_RDN "cn=replica"
int slapi_log_urp = SLAPI_LOG_REPL;
+static ReplicaId cleaned_rid = 0;
+static int released_rid = 0;
/* Forward Declartions */
static int replica_config_add (Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg);
@@ -74,6 +80,9 @@ static int replica_execute_task (Object *r, const char *task_name, char *returnt
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 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);
@@ -825,10 +834,8 @@ static int replica_execute_task (Object *r, const char *task_name, char *returnt
{
int temprid = atoi(&(task_name[CLEANRUVLEN]));
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);
+ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Invalid replica id (%d) for task - %s", temprid, task_name);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_execute_task: %s\n", returntext);
return LDAP_OPERATIONS_ERROR;
}
if (apply_mods)
@@ -838,6 +845,36 @@ static int replica_execute_task (Object *r, const char *task_name, char *returnt
else
return LDAP_SUCCESS;
}
+ else if (strncasecmp (task_name, CLEANALLRUV, CLEANALLRUVLEN) == 0)
+ {
+ int temprid = atoi(&(task_name[CLEANALLRUVLEN]));
+ if (temprid <= 0 || temprid >= READ_ONLY_REPLICA_ID){
+ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Invalid replica id (%d) for task - (%s)", temprid, 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_cleanall_ruv_task(r, (ReplicaId)temprid, returntext);
+ }
+ 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);
@@ -1099,16 +1136,24 @@ _replica_config_get_mtnode_ext (const Slapi_Entry *e)
return ext;
}
+int
+replica_execute_cleanruv_task_ext(Object *r, ReplicaId rid)
+{
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanruv_extop: calling clean_ruv_ext\n");
+ return replica_execute_cleanruv_task(r, rid, NULL);
+}
+
static int
-replica_execute_cleanruv_task (Object *r, ReplicaId rid, char *returntext)
+replica_execute_cleanruv_task (Object *r, ReplicaId rid, char *returntext /* not used */)
{
int rc = 0;
Object *RUVObj;
RUV *local_ruv = NULL;
- Replica *replica = (Replica*)object_get_data (r);
+ Replica *replica = (Replica*)object_get_data (r);
- PR_ASSERT (replica);
+ PR_ASSERT (replica);
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanruv_task: cleaning rid (%d)...\n",(int)rid);
RUVObj = replica_get_ruv(replica);
PR_ASSERT(RUVObj);
local_ruv = (RUV*)object_get_data (RUVObj);
@@ -1128,10 +1173,295 @@ replica_execute_cleanruv_task (Object *r, ReplicaId rid, char *returntext)
/* Update Mapping Tree to reflect RUV changes */
consumer5_set_mapping_tree_state_for_replica(replica, NULL);
+ /*
+ * Clean the changelog RUV's, and set the rids
+ */
+ cl5CleanRUV(rid);
+ set_cleaned_rid(rid);
+ delete_released_rid();
+
if (rc != RUV_SUCCESS){
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanruv_task: task failed(%d)\n",rc);
return LDAP_OPERATIONS_ERROR;
}
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanruv_task: finished successfully\n");
return LDAP_SUCCESS;
}
+static int
+replica_execute_cleanall_ruv_task (Object *r, ReplicaId rid, char *returntext)
+{
+ Repl_Connection *conn;
+ Replica *replica = (Replica*)object_get_data (r);
+ Object *agmt_obj;
+ Repl_Agmt *agmt;
+ ConnResult crc;
+ const Slapi_DN *dn = NULL;
+ struct berval *payload = NULL;
+ char *ridstr = NULL;
+ int send_msgid = 0;
+ int rc = 0;
+
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanAllRUV_task: cleaning rid (%d)...\n",(int)rid);
+
+ /*
+ * Create payload
+ */
+ ridstr = slapi_ch_smprintf("%d:%s", rid, slapi_sdn_get_dn(replica_get_root(replica)));
+ payload = create_ruv_payload(ridstr);
+ if(payload == NULL){
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: failed to create ext op payload, aborting task\n");
+ goto done;
+ }
+
+ agmt_obj = agmtlist_get_first_agreement_for_replica (replica);
+ while (agmt_obj)
+ {
+ agmt = (Repl_Agmt*)object_get_data (agmt_obj);
+ dn = agmt_get_dn_byref(agmt);
+ conn = (Repl_Connection *)agmt_get_connection(agmt);
+ if(conn == NULL){
+ /* no connection for this agreement, and move on */
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: 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 (replica, agmt_obj);
+ continue;
+ }
+ crc = conn_connect(conn);
+ if (CONN_OPERATION_FAILED == crc ){
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: failed to connect "
+ "to repl agreement connection (%s), error %d\n",slapi_sdn_get_dn(dn), ACQUIRE_TRANSIENT_ERROR);
+ } else if (CONN_SSL_NOT_ENABLED == crc){
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: failed to acquire "
+ "repl agmt connection (%s), errror %d\n",slapi_sdn_get_dn(dn), ACQUIRE_FATAL_ERROR);
+ } else {
+ conn_cancel_linger(conn);
+ crc = conn_send_extended_operation(conn, REPL_CLEANRUV_OID, payload, NULL, &send_msgid);
+ if (CONN_OPERATION_SUCCESS != crc){
+ 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 "
+ "cleanruv 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, "cleanAllRUV_task: replica (%s) has not "
+ "been cleaned. You will need to rerun the CLEANALLRUV task on this replica.\n", slapi_sdn_get_dn(dn));
+ rc = crc;
+ }
+ agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj);
+ }
+
+done:
+
+ if(payload)
+ ber_bvfree(payload);
+
+ slapi_ch_free_string(&ridstr);
+
+ /*
+ * Now run the cleanruv task
+ */
+ replica_execute_cleanruv_task (r, rid, returntext);
+
+ if(rc == 0){
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanAllRUV_task: operation successful\n");
+ } else {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: operation failed (%d)\n",rc);
+ }
+
+ return rc;
+}
+
+static int
+replica_execute_release_ruv_task(Object *r, ReplicaId rid, char *returntext)
+{
+ Repl_Connection *conn;
+ Replica *replica = (Replica*)object_get_data (r);
+ Object *agmt_obj;
+ Repl_Agmt *agmt;
+ ConnResult crc;
+ const Slapi_DN *dn = NULL;
+ struct berval *payload = NULL;
+ char *ridstr = NULL;
+ int send_msgid = 0;
+ int rc = 0;
+
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "releaseRUV_task: releasing rid (%d)...\n", rid);
+
+ /*
+ * Set the released rid, and trigger cl trimmming
+ */
+ set_released_rid((int)rid);
+ trigger_cl_trimming();
+ /*
+ * Create payload
+ */
+ ridstr = slapi_ch_smprintf("%d:%s", rid, slapi_sdn_get_dn(replica_get_root(replica)));
+ payload = create_ruv_payload(ridstr);
+ if(payload == NULL){
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseRUV_task: failed to create ext op payload, aborting op\n");
+ rc = -1;
+ goto done;
+ }
+
+ agmt_obj = agmtlist_get_first_agreement_for_replica (replica);
+ while (agmt_obj)
+ {
+ agmt = (Repl_Agmt*)object_get_data (agmt_obj);
+ dn = agmt_get_dn_byref(agmt);
+ conn = (Repl_Connection *)agmt_get_connection(agmt);
+ if(conn == NULL){
+ /* no connection for this agreement, log error, and move on */
+ agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj);
+ continue;
+ }
+ crc = conn_connect(conn);
+ if (CONN_OPERATION_FAILED == crc ){
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseRUV_task: failed to connect "
+ "to repl agmt (%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_task: failed to acquire "
+ "repl agmt (%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, 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);
+ 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));
+ }
+ 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_sdn_get_dn(dn));
+ rc = crc;
+ }
+ agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj);
+ }
+
+done:
+ /*
+ * reset the released/clean rid
+ */
+ 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);
+ } else {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseRUV_task: Failed to release rid (%d), error (%d)\n", rid, rc);
+ }
+
+ if(payload)
+ ber_bvfree(payload);
+
+ slapi_ch_free_string(&ridstr);
+
+ return rc;
+}
+
+static struct berval *
+create_ruv_payload(char *value){
+ struct berval *req_data = NULL;
+ BerElement *tmp_bere = NULL;
+ if ((tmp_bere = der_alloc()) == NULL){
+ goto error;
+ }
+ if (ber_printf(tmp_bere, "{s", value) == -1){
+ goto error;
+ }
+
+ if (ber_printf(tmp_bere, "}") == -1){
+ goto error;
+ }
+
+ if (ber_flatten(tmp_bere, &req_data) == -1){
+ goto error;
+ }
+
+ goto done;
+
+error:
+ if (NULL != req_data){
+ ber_bvfree(req_data);
+ req_data = NULL;
+ }
+
+done:
+ if (NULL != tmp_bere){
+ ber_free(tmp_bere, 1);
+ tmp_bere = NULL;
+ }
+
+ return req_data;
+}
+
+int
+is_cleaned_rid(ReplicaId rid)
+{
+ if(rid == cleaned_rid){
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+void
+set_cleaned_rid( ReplicaId rid )
+{
+ cleaned_rid = rid;
+}
+
+void
+delete_cleaned_rid()
+{
+ cleaned_rid = 0;
+}
+
+int
+get_released_rid()
+{
+ return released_rid;
+}
+
+int
+is_released_rid(int rid)
+{
+ if(rid == released_rid){
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+int
+is_already_released_rid()
+{
+ if(released_rid == ALREADY_RELEASED){
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+void
+set_released_rid( int rid )
+{
+ released_rid = rid;
+}
+
+void
+delete_released_rid()
+{
+ released_rid = 0;
+}
diff --git a/ldap/servers/plugins/replication/repl5_ruv.c b/ldap/servers/plugins/replication/repl5_ruv.c
index 9a80fcc..9ad5c5a 100644
--- a/ldap/servers/plugins/replication/repl5_ruv.c
+++ b/ldap/servers/plugins/replication/repl5_ruv.c
@@ -863,10 +863,27 @@ ruv_covers_csn_internal(const RUV *ruv, const CSN *csn, PRBool strict)
{
rid = csn_get_replicaid(csn);
replica = ruvGetReplica (ruv, rid);
+ if((is_released_rid(rid)) || (replica == NULL && is_already_released_rid()) ){
+ /* this is a released rid, so return true */
+ return PR_TRUE;
+ }
if (replica == NULL)
{
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "ruv_covers_csn: replica for id %d not found\n", rid);
- return_value = PR_FALSE;
+ /*
+ * We don't know anything about this replica change in the cl, mark it to be zapped.
+ * This could of been a previously cleaned ruv, but the server was restarted before
+ * the change could be trimmed.
+ *
+ * Only the change log trimming calls this function with "strict" set. So we'll return success
+ * if strict is set.
+ */
+ if(strict){
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "ruv_covers_csn: replica for id %d not found.\n", rid);
+ return_value = PR_TRUE;
+ } else {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "ruv_covers_csn: replica for id %d not found.\n", rid);
+ return_value = PR_FALSE;
+ }
}
else
{
@@ -1403,12 +1420,20 @@ int ruv_add_csn_inprogress (RUV *ruv, const CSN *csn)
RUVElement* replica;
char csn_str[CSN_STRSIZE];
int rc = RUV_SUCCESS;
+ int rid = csn_get_replicaid (csn);
PR_ASSERT (ruv && csn);
/* locate ruvElement */
slapi_rwlock_wrlock (ruv->lock);
- replica = ruvGetReplica (ruv, csn_get_replicaid (csn));
+
+ if(is_cleaned_rid(rid)){
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "ruv_add_csn_inprogress: invalid replica ID"
+ "(%d), aborting update\n", rid);
+ /* return success because we want to consume the update, but not perform it */
+ goto done;
+ }
+ replica = ruvGetReplica (ruv, rid);
if (replica == NULL)
{
replica = ruvAddReplicaNoCSN (ruv, csn_get_replicaid (csn), NULL/*purl*/);
@@ -1416,7 +1441,7 @@ int ruv_add_csn_inprogress (RUV *ruv, const CSN *csn)
{
if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) {
slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "ruv_add_csn_inprogress: failed to add replica"
- " that created csn %s\n", csn_as_string (csn, PR_FALSE, csn_str));
+ " that created csn %s\n", csn_as_string (csn, PR_FALSE, csn_str));
}
rc = RUV_MEMORY_ERROR;
goto done;
diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c
index 2ff3627..7e2ebbd 100644
--- a/ldap/servers/plugins/replication/repl_extop.c
+++ b/ldap/servers/plugins/replication/repl_extop.c
@@ -71,6 +71,7 @@
*
*/
static int check_replica_id_uniqueness(Replica *replica, RUV *supplier_ruv);
+static multimaster_mtnode_extension *replica_config_get_mtnode_by_dn(const char *dn);
static int
encode_ruv (BerElement *ber, const RUV *ruv)
@@ -1260,7 +1261,6 @@ multimaster_extop_EndNSDS50ReplicationRequest(Slapi_PBlock *pb)
{
/* The ruv from the supplier may have changed. Report the change on the
consumer side */
-
replica_update_ruv_consumer(r, connext->supplier_ruv);
}
@@ -1315,6 +1315,345 @@ free_and_return:
}
/*
+ * Return the mtnode extension of the dn
+ */
+static multimaster_mtnode_extension *
+replica_config_get_mtnode_by_dn(const char *dn)
+{
+ Slapi_DN *sdn;
+ mapping_tree_node *mtnode;
+ multimaster_mtnode_extension *ext = NULL;
+
+ sdn = slapi_sdn_new_dn_byval(dn);
+ mtnode = slapi_get_mapping_tree_node_by_dn (sdn);
+ if (mtnode) {
+ /* check if the replica object already exists in the subtree */
+ ext = (multimaster_mtnode_extension *)repl_con_get_ext (REPL_CON_EXT_MTNODE, mtnode);
+ }
+ slapi_sdn_free (&sdn);
+
+ return ext;
+}
+
+/*
+ * Decode the ber element passed to us by the cleanAllRUV task
+ */
+static int
+decode_cleanruv_payload(struct berval *extop_value, char **payload)
+{
+ BerElement *tmp_bere = NULL;
+ int rc = 0;
+
+ if ((tmp_bere = ber_init(extop_value)) == NULL){
+ rc = -1;
+ goto free_and_return;
+ }
+ if (ber_scanf(tmp_bere, "{") == LBER_ERROR){
+ rc = -1;
+ goto free_and_return;
+ }
+ if (ber_get_stringa(tmp_bere, payload) == LBER_DEFAULT){
+ rc = -1;
+ goto free_and_return;
+ }
+
+ if (ber_scanf(tmp_bere, "}") == LBER_ERROR){
+ rc = -1;
+ goto free_and_return;
+ }
+
+free_and_return:
+ if (-1 == rc){
+ slapi_ch_free_string(payload);
+ }
+ if (NULL != tmp_bere){
+ ber_free(tmp_bere, 1);
+ tmp_bere = NULL;
+ }
+ return rc;
+}
+
+/*
+ * Process the REPL_CLEANRUV_OID extended operation.
+ *
+ * The payload consists of the replica ID, and the repl root dn. Since this is
+ * basically a replication operation, it could of originated here and bounced
+ * back from another master. So check the rid against the "cleaned_rid". If
+ * it's a match, then we were already here, and we can just return success.
+ *
+ * Otherwise, we the set the cleaned_rid from the payload, fire off extended ops
+ * to all the replica agreements on this replica. Then perform the actual
+ * cleanruv_task on this replica.
+ */
+int
+multimaster_extop_cleanruv(Slapi_PBlock *pb){
+ multimaster_mtnode_extension *mtnode_ext;
+ Repl_Connection *conn;
+ const Slapi_DN *dn;
+ Replica *r = NULL;
+ Object *agmt_obj;
+ Repl_Agmt *agmt;
+ ConnResult crc;
+ struct berval *extop_value;
+ char *extop_oid;
+ char *repl_root;
+ char *payload = NULL;
+ char *iter;
+ int send_msgid = 0;
+ int rid = 0;
+ int rc = 0;
+
+ slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &extop_oid);
+ slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value);
+
+ if (NULL == extop_oid || strcmp(extop_oid, REPL_CLEANRUV_OID) != 0 ||
+ NULL == extop_value || NULL == extop_value->bv_val){
+ /* 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");
+ 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);
+ return rc;
+ } else {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanruv_extop: cleaning rid (%d)...\n", 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 "
+ "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), "
+ "aborting operation\n",repl_root);
+ rc = LDAP_OPERATIONS_ERROR;
+ goto free_and_return;
+ }
+ r = (Replica*)object_get_data (mtnode_ext->replica);
+ /*
+ * Send out extended ops to each repl agreement
+ */
+ agmt_obj = agmtlist_get_first_agreement_for_replica (r);
+ while (agmt_obj)
+ {
+ agmt = (Repl_Agmt*)object_get_data (agmt_obj);
+ dn = agmt_get_dn_byref(agmt);
+ 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 "
+ "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 "
+ "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 "
+ "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 "
+ "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 "
+ "extended op to (%s)\n",slapi_sdn_get_dn(dn) );
+ }
+ conn_start_linger(conn);
+ }
+ if(crc != CONN_OPERATION_SUCCESS){
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanruv_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;
+ }
+ agmt_obj = agmtlist_get_next_agreement_for_replica (r, agmt_obj);
+ }
+
+ /* now clean the ruv */
+ replica_execute_cleanruv_task_ext(mtnode_ext->replica, rid);
+
+free_and_return:
+
+ if(rc == 0){
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanruv_extop: cleaned rid (%d)\n", rid);
+ } else {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanruv_extop: failed to clean rid (%d), error (%d)\n",rid, rc);
+ }
+
+ if (mtnode_ext->replica)
+ object_release (mtnode_ext->replica);
+
+ return rc;
+}
+
+/*
+ * Process the REPL_RELEASERUV_OID extended operation
+ *
+ * Once, all the replicas in the replication farm have been cleaned, then
+ * we need to "release" the cleaned_rid, or else we will reject all updates
+ * that come from that rid until we restart the server.
+ *
+ * We set the cleaned_ruv to zero(invalid rid), and then fire off extended
+ * operations to all of the replicas
+ */
+int
+multimaster_extop_releaseruv(Slapi_PBlock *pb){
+ multimaster_mtnode_extension *mtnode_ext;
+ Repl_Connection *conn;
+ const Slapi_DN *dn;
+ Replica *r = NULL;
+ Object *agmt_obj;
+ Repl_Agmt *agmt;
+ ConnResult crc;
+ struct berval *extop_value;
+ char *payload = NULL;
+ char *extop_oid;
+ char *repl_root;
+ char *iter;
+ int send_msgid = 0;
+ int rid = 0;
+ int rc = -1;
+
+ slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &extop_oid);
+ slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value);
+
+ if (NULL == extop_oid || strcmp(extop_oid, REPL_RELEASERUV_OID) != 0 ||
+ NULL == extop_value || NULL == extop_value->bv_val){
+ /* something is wrong, error out */
+ return -1;
+ }
+
+ 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");
+ 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);
+ return 0;
+ } else {
+ /* set the released rid, and trigger trimming */
+ 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 "
+ "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), "
+ "aborting operation.\n", repl_root);
+ rc = LDAP_OPERATIONS_ERROR;
+ goto free_and_return;
+ }
+ r = (Replica*)object_get_data (mtnode_ext->replica);
+ /*
+ * Loop over the agreements, and send out extended ops
+ */
+ agmt_obj = agmtlist_get_first_agreement_for_replica (r);
+ while (agmt_obj)
+ {
+ agmt = (Repl_Agmt*)object_get_data (agmt_obj);
+ dn = agmt_get_dn_byref(agmt);
+ 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));
+ 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 "
+ "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 "
+ "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);
+ 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) );
+ 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_sdn_get_dn(dn) );
+ }
+ agmt_obj = agmtlist_get_next_agreement_for_replica (r, agmt_obj);
+ }
+
+free_and_return:
+ /*
+ * Set the rid as "ALREADY_RELEASED, and remove the cleaned ruv
+ */
+ 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);
+ } 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);
+ }
+
+ if(mtnode_ext->replica)
+ object_release (mtnode_ext->replica);
+
+ return rc;
+}
+
+/*
* This plugin entry point is a noop entry
* point. It's used when registering extops that
* are only used as responses. We'll never receive
11 years, 1 month
ldap/servers
by Mark Reynolds
ldap/servers/plugins/memberof/memberof.c | 233 ++++++++++++------------
ldap/servers/plugins/memberof/memberof.h | 3
ldap/servers/plugins/memberof/memberof_config.c | 33 +++
3 files changed, 160 insertions(+), 109 deletions(-)
New commits:
commit 118e483ca9240b32f0e36dd74dc9f88669220ee7
Author: root <root(a)localhost.localdomain>
Date: Tue Apr 24 17:40:35 2012 -0400
Ticket #326 - MemberOf plugin should work on all backends
Bug Description: By design the memberOf plugin would only look at the backend from
which the group belonged to. This makes it impossible to maintain
users and groups from different suffixes.
Fix Description: First I added a new config setting in the plugin to turn this on
and off. Then we just look at all the backends when searching.
https://fedorahosted.org/389/ticket/326
Reviewed by: ?
diff --git a/ldap/servers/plugins/memberof/memberof.c b/ldap/servers/plugins/memberof/memberof.c
index 655054c..229b962 100644
--- a/ldap/servers/plugins/memberof/memberof.c
+++ b/ldap/servers/plugins/memberof/memberof.c
@@ -67,10 +67,8 @@
#endif
#include "slapi-plugin.h"
-
#include "string.h"
#include "nspr.h"
-
#include "memberof.h"
static Slapi_PluginDesc pdesc = { "memberof", VENDOR,
@@ -507,94 +505,101 @@ int memberof_del_dn_type_callback(Slapi_Entry *e, void *callback_data)
}
/*
- * Does a callback search of "type=dn" under the db suffix that "dn" is in.
- * If "dn" is a user, you'd want "type" to be "member". If "dn" is a group,
- * you could want type to be either "member" or "memberOf" depending on the
- * case.
+ * Does a callback search of "type=dn" under the db suffix that "dn" is in,
+ * unless all_backends is set, then we look at all the backends. If "dn"
+ * is a user, you'd want "type" to be "member". If "dn" is a group, you
+ * could want type to be either "member" or "memberOf" depending on the case.
*/
int memberof_call_foreach_dn(Slapi_PBlock *pb, char *dn,
char **types, plugin_search_entry_callback callback, void *callback_data)
{
- int rc = 0;
Slapi_PBlock *search_pb = slapi_pblock_new();
- Slapi_Backend *be = 0;
- Slapi_DN *sdn = 0;
- Slapi_DN *base_sdn = 0;
- char *filter_str = 0;
- int num_types = 0;
+ Slapi_DN *base_sdn = NULL;
+ Slapi_Backend *be = NULL;
+ Slapi_DN *sdn = NULL;
+ char *filter_str = NULL;
+ char *cookie = NULL;
+ int all_backends = memberof_config_get_all_backends();
int types_name_len = 0;
- int dn_len = 0;
+ int num_types = 0;
+ int dn_len = strlen(dn);
+ int rc = 0;
int i = 0;
- /* get the base dn for the backend we are in
- (we don't support having members and groups in
- different backends - issues with offline / read only backends)
- */
- sdn = slapi_sdn_new_normdn_byref(dn);
- be = slapi_be_select(sdn);
- if(be)
+ /* Count the number of types. */
+ for (num_types = 0; types && types[num_types]; num_types++)
{
- base_sdn = (Slapi_DN*)slapi_be_getsuffix(be,0);
+ /* Add up the total length of all attribute names.
+ * We need to know this for building the filter. */
+ types_name_len += strlen(types[num_types]);
}
- if(base_sdn)
+ /* Build the search filter. */
+ if (num_types > 1)
{
- /* Find the length of the dn */
- dn_len = strlen(dn);
+ int bytes_out = 0;
+ int filter_str_len = types_name_len + (num_types * (3 + dn_len)) + 4;
- /* Count the number of types. */
- for (num_types = 0; types && types[num_types]; num_types++)
- {
- /* Add up the total length of all attribute names.
- * We need to know this for building the filter. */
- types_name_len += strlen(types[num_types]);
- }
+ /* Allocate enough space for the filter */
+ filter_str = slapi_ch_malloc(filter_str_len);
- /* Build the search filter. */
- if (num_types > 1)
+ /* Add beginning of filter. */
+ bytes_out = snprintf(filter_str, filter_str_len - bytes_out, "(|");
+
+ /* Add filter section for each type. */
+ for (i = 0; types[i]; i++)
{
- int bytes_out = 0;
- int filter_str_len = types_name_len + (num_types * (3 + dn_len)) + 4;
+ bytes_out += snprintf(filter_str + bytes_out, filter_str_len - bytes_out,
+ "(%s=%s)", types[i], dn);
+ }
- /* Allocate enough space for the filter */
- filter_str = slapi_ch_malloc(filter_str_len);
+ /* Add end of filter. */
+ snprintf(filter_str + bytes_out, filter_str_len - bytes_out, ")");
+ }
+ else if (num_types == 1)
+ {
+ filter_str = slapi_ch_smprintf("(%s=%s)", types[0], dn);
+ }
- /* Add beginning of filter. */
- bytes_out = snprintf(filter_str, filter_str_len - bytes_out, "(|");
+ if(filter_str == NULL){
+ return rc;
+ }
- /* Add filter section for each type. */
- for (i = 0; types[i]; i++)
- {
- bytes_out += snprintf(filter_str + bytes_out, filter_str_len - bytes_out,
- "(%s=%s)", types[i], dn);
+ be = slapi_get_first_backend(&cookie);
+ while(be){
+ if(!all_backends){
+ sdn = slapi_sdn_new_normdn_byref(dn);
+ be = slapi_be_select(sdn);
+ if(be == NULL){
+ break;
}
-
- /* Add end of filter. */
- snprintf(filter_str + bytes_out, filter_str_len - bytes_out, ")");
}
- else if (num_types == 1)
- {
- filter_str = slapi_ch_smprintf("(%s=%s)", types[0], dn);
+ if((base_sdn = (Slapi_DN *)slapi_be_getsuffix(be,0)) == NULL){
+ if(!all_backends){
+ break;
+ } else {
+ /* its ok, goto the next backend */
+ be = slapi_get_next_backend(cookie);
+ continue;
+ }
}
- }
- if(filter_str)
- {
slapi_search_internal_set_pb(search_pb, slapi_sdn_get_dn(base_sdn),
- LDAP_SCOPE_SUBTREE, filter_str, 0, 0,
- 0, 0,
- memberof_get_plugin_id(),
- 0);
-
- slapi_search_internal_callback_pb(search_pb,
- callback_data,
- 0, callback,
- 0);
+ LDAP_SCOPE_SUBTREE, filter_str, 0, 0, 0, 0, memberof_get_plugin_id(), 0);
+ slapi_search_internal_callback_pb(search_pb, callback_data, 0, callback, 0);
+
+ if(!all_backends){
+ break;
+ }
+ slapi_pblock_init(search_pb);
+ be = slapi_get_next_backend(cookie);
}
slapi_sdn_free(&sdn);
slapi_pblock_destroy(search_pb);
+ slapi_ch_free((void **)&cookie);
slapi_ch_free_string(&filter_str);
+
return rc;
}
@@ -1123,60 +1128,72 @@ int memberof_modop_one_replace_r(Slapi_PBlock *pb, MemberOfConfig *config,
Slapi_DN *base_sdn = 0;
Slapi_Backend *be = 0;
char *filter_str = 0;
+ char *cookie = NULL;
int n_entries = 0;
-
- /* We can't tell for sure if the op_to entry is a
- * user or a group since the entry doesn't exist
- * anymore. We can safely ignore the missing entry
- * if no other entries have a memberOf attribute that
- * points to the missing entry. */
- be = slapi_be_select(op_to_sdn);
- if(be)
- {
- base_sdn = (Slapi_DN*)slapi_be_getsuffix(be,0);
- }
-
- if(base_sdn)
- {
- filter_str = slapi_ch_smprintf("(%s=%s)",
- config->memberof_attr, op_to);
- }
-
- if(filter_str)
- {
- slapi_search_internal_set_pb(search_pb, slapi_sdn_get_dn(base_sdn),
- LDAP_SCOPE_SUBTREE, filter_str, 0, 0, 0, 0,
- memberof_get_plugin_id(), 0);
-
- if (slapi_search_internal_pb(search_pb))
+ int all_backends = config->allBackends;
+
+ filter_str = slapi_ch_smprintf("(%s=%s)", config->memberof_attr, op_to);
+ be = slapi_get_first_backend(&cookie);
+ while(be){
+ /*
+ * We can't tell for sure if the op_to entry is a
+ * user or a group since the entry doesn't exist
+ * anymore. We can safely ignore the missing entry
+ * if no other entries have a memberOf attribute that
+ * points to the missing entry.
+ */
+ if(!all_backends){
+ be = slapi_be_select(op_to_sdn);
+ if(be == NULL){
+ break;
+ }
+ }
+ if((base_sdn = (Slapi_DN*)slapi_be_getsuffix(be,0)) == NULL){
+ if(!all_backends){
+ break;
+ } else {
+ be = slapi_get_next_backend (cookie);
+ continue;
+ }
+ }
+ if(filter_str)
{
- /* get result and log an error */
- int res = 0;
- slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
- slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
- "memberof_modop_one_replace_r: error searching for members: "
- "%d", res);
- } else {
- slapi_pblock_get(search_pb, SLAPI_NENTRIES, &n_entries);
-
- if(n_entries > 0)
+ slapi_search_internal_set_pb(search_pb, slapi_sdn_get_dn(base_sdn),
+ LDAP_SCOPE_SUBTREE, filter_str, 0, 0, 0, 0,
+ memberof_get_plugin_id(), 0);
+
+ if (slapi_search_internal_pb(search_pb))
{
- /* We want to fixup the membership for the
- * entries that referred to the missing group
- * entry. This will fix the references to
- * the missing group as well as the group
- * represented by op_this. */
- memberof_test_membership(pb, config, op_to);
+ /* get result and log an error */
+ int res = 0;
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
+ slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
+ "memberof_modop_one_replace_r: error searching for members: "
+ "%d", res);
+ } else {
+ slapi_pblock_get(search_pb, SLAPI_NENTRIES, &n_entries);
+ if(n_entries > 0)
+ {
+ /* We want to fixup the membership for the
+ * entries that referred to the missing group
+ * entry. This will fix the references to
+ * the missing group as well as the group
+ * represented by op_this. */
+ memberof_test_membership(pb, config, op_to);
+ }
}
+ slapi_free_search_results_internal(search_pb);
}
-
- slapi_free_search_results_internal(search_pb);
- slapi_ch_free_string(&filter_str);
+ slapi_pblock_init(search_pb);
+ if(!all_backends){
+ break;
+ }
+ be = slapi_get_next_backend (cookie);
}
-
slapi_pblock_destroy(search_pb);
+ slapi_ch_free_string(&filter_str);
+ slapi_ch_free((void **)&cookie);
}
-
goto bail;
}
diff --git a/ldap/servers/plugins/memberof/memberof.h b/ldap/servers/plugins/memberof/memberof.h
index fdf1253..36901e3 100644
--- a/ldap/servers/plugins/memberof/memberof.h
+++ b/ldap/servers/plugins/memberof/memberof.h
@@ -65,6 +65,7 @@
#define MEMBEROF_INT_PREOP_DESC "memberOf internal postop plugin"
#define MEMBEROF_GROUP_ATTR "memberOfGroupAttr"
#define MEMBEROF_ATTR "memberOfAttr"
+#define MEMBEROF_BACKEND_ATTR "memberOfAllBackends"
#define DN_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.12"
#define NAME_OPT_UID_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.34"
@@ -75,6 +76,7 @@
typedef struct memberofconfig {
char **groupattrs;
char *memberof_attr;
+ int allBackends;
Slapi_Filter *group_filter;
Slapi_Attr **group_slapiattrs;
} MemberOfConfig;
@@ -92,6 +94,7 @@ void memberof_unlock();
void memberof_rlock_config();
void memberof_wlock_config();
void memberof_unlock_config();
+int memberof_config_get_all_backends();
int g_get_shutdown(); /* declared in proto-slap.h */
diff --git a/ldap/servers/plugins/memberof/memberof_config.c b/ldap/servers/plugins/memberof/memberof_config.c
index a30d448..b4d557a 100644
--- a/ldap/servers/plugins/memberof/memberof_config.c
+++ b/ldap/servers/plugins/memberof/memberof_config.c
@@ -270,11 +270,13 @@ memberof_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
char *filter_str = NULL;
int num_groupattrs = 0;
int groupattr_name_len = 0;
+ char *allBackends = NULL;
*returncode = LDAP_SUCCESS;
groupattrs = slapi_entry_attr_get_charray(e, MEMBEROF_GROUP_ATTR);
- memberof_attr = slapi_entry_attr_get_charptr(e, MEMBEROF_ATTR);
+ memberof_attr = slapi_entry_attr_get_charptr(e, MEMBEROF_ATTR);
+ allBackends = slapi_entry_attr_get_charptr(e, MEMBEROF_BACKEND_ATTR);
/* We want to be sure we don't change the config in the middle of
* a memberOf operation, so we obtain an exclusive lock here */
@@ -373,11 +375,23 @@ memberof_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
memberof_attr = NULL; /* config now owns memory */
}
+ if (allBackends)
+ {
+ if(strcasecmp(allBackends,"on")==0){
+ theConfig.allBackends = 1;
+ } else {
+ theConfig.allBackends = 0;
+ }
+ } else {
+ theConfig.allBackends = 0;
+ }
+
/* release the lock */
memberof_unlock_config();
slapi_ch_array_free(groupattrs);
slapi_ch_free_string(&memberof_attr);
+ slapi_ch_free_string(&allBackends);
if (*returncode != LDAP_SUCCESS)
{
@@ -449,6 +463,11 @@ memberof_copy_config(MemberOfConfig *dest, MemberOfConfig *src)
slapi_ch_free_string(&dest->memberof_attr);
dest->memberof_attr = slapi_ch_strdup(src->memberof_attr);
}
+
+ if(src->allBackends)
+ {
+ dest->allBackends = src->allBackends;
+ }
}
}
@@ -526,3 +545,15 @@ memberof_unlock_config()
{
slapi_rwlock_unlock(memberof_config_lock);
}
+
+int
+memberof_config_get_all_backends()
+{
+ int all_backends;
+
+ slapi_rwlock_rdlock(memberof_config_lock);
+ all_backends = theConfig.allBackends;
+ slapi_rwlock_unlock(memberof_config_lock);
+
+ return all_backends;
+}
11 years, 1 month
ldap/servers
by Noriko Hosoi
ldap/servers/plugins/usn/usn.c | 152 +++++++++++++----------------
ldap/servers/slapd/back-ldbm/ldbm_delete.c | 107 ++++++++------------
ldap/servers/slapd/pblock.c | 12 ++
ldap/servers/slapd/plugin.c | 1
ldap/servers/slapd/slap.h | 3
ldap/servers/slapd/slapi-plugin.h | 2
6 files changed, 129 insertions(+), 148 deletions(-)
New commits:
commit a5ed82445832092277f5edf2d0440c8d1e931619
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Tue Apr 24 17:54:56 2012 -0700
Trac Ticket #19 - Convert entryUSN plugin to transaction aware type
https://fedorahosted.org/389/ticket/19
Fix description:
. Separated usn_bepreop operations from usn_betxnpreop operations.
usn_bepreop_modify and _modrdn add "entryusn: #" to the mods,
which should be handled before the transaction starts.
. Introduced SLAPI_PLUGIN_BE_TXN_PRE_DELETE_TOMBSTONE_FN plugin
hook to modify the tombstone entry at the betxn timing.
. Eliminated preventryusn (SLAPI_ATTR_ENTRYUSN_PREV). It was used
to undo the incremented entryusn when the deletion fails.
Since the operation is now executed in the transaction and it
is aborted if the operation fails, the explicit undo is not
needed in the usn postop.
Reviewed by Rich. (Thank you!!)
diff --git a/ldap/servers/plugins/usn/usn.c b/ldap/servers/plugins/usn/usn.c
index 617589e..0d8a065 100644
--- a/ldap/servers/plugins/usn/usn.c
+++ b/ldap/servers/plugins/usn/usn.c
@@ -51,16 +51,18 @@ static void *_usn_identity = NULL;
static int usn_preop_init(Slapi_PBlock *pb);
static int usn_bepreop_init(Slapi_PBlock *pb);
+static int usn_betxnpreop_init(Slapi_PBlock *pb);
static int usn_bepostop_init(Slapi_PBlock *pb);
static int usn_rootdse_init();
static int usn_preop_delete(Slapi_PBlock *pb);
-static int usn_bepreop_add(Slapi_PBlock *pb);
-static int usn_bepreop_delete(Slapi_PBlock *pb);
static int usn_bepreop_modify(Slapi_PBlock *pb);
+static int usn_betxnpreop_add(Slapi_PBlock *pb);
+static int usn_betxnpreop_delete(Slapi_PBlock *pb);
static int usn_bepostop(Slapi_PBlock *pb);
static int usn_bepostop_delete (Slapi_PBlock *pb);
static int usn_bepostop_modify (Slapi_PBlock *pb);
+
static int usn_start(Slapi_PBlock *pb);
static int usn_close(Slapi_PBlock *pb);
static int usn_get_attr(Slapi_PBlock *pb, const char* type, void *value);
@@ -78,8 +80,8 @@ usn_init(Slapi_PBlock *pb)
{
int rc = 0;
void *identity = NULL;
- Slapi_Entry *plugin_entry = NULL;
- int is_betxn = 0;
+ Slapi_Entry *plugin_entry = NULL;
+ int is_betxn = 0;
const char *plugintype;
slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
@@ -87,10 +89,11 @@ usn_init(Slapi_PBlock *pb)
slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &identity);
- if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry) == 0) &&
- plugin_entry) {
- is_betxn = slapi_entry_attr_get_bool(plugin_entry, "nsslapd-pluginbetxn");
- }
+ if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry) == 0) &&
+ plugin_entry) {
+ is_betxn = slapi_entry_attr_get_bool(plugin_entry,
+ "nsslapd-pluginbetxn");
+ }
/* slapi_register_plugin always returns SUCCESS (0) */
if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION,
@@ -112,20 +115,23 @@ usn_init(Slapi_PBlock *pb)
goto bail;
}
+ /* usn_preop_init: plugintype is preoperation (not be/betxn) */
plugintype = "preoperation";
- if (is_betxn) {
- plugintype = "betxnpreoperation";
- }
rc = slapi_register_plugin(plugintype, 1 /* Enabled */,
"usn_preop_init", usn_preop_init,
"USN preoperation plugin", NULL, identity);
+
+ /* usn_bepreop_init: plugintype is bepreoperation (not betxn) */
plugintype = "bepreoperation";
- if (is_betxn) {
- plugintype = "betxnpreoperation";
- }
rc |= slapi_register_plugin(plugintype, 1 /* Enabled */,
"usn_bepreop_init", usn_bepreop_init,
"USN bepreoperation plugin", NULL, identity);
+
+ /* usn_bepreop_init: plugintype is betxnpreoperation */
+ plugintype = "betxnpreoperation";
+ rc |= slapi_register_plugin(plugintype, 1 /* Enabled */,
+ "usn_betxnpreop_init", usn_betxnpreop_init,
+ "USN betxnpreoperation plugin", NULL, identity);
plugintype = "bepostoperation";
if (is_betxn) {
plugintype = "betxnpostoperation";
@@ -140,22 +146,12 @@ bail:
return rc;
}
+/* This ops must be preop not be/betxn */
static int
usn_preop_init(Slapi_PBlock *pb)
{
int rc = 0;
- Slapi_Entry *plugin_entry = NULL;
- char *plugin_type = NULL;
int predel = SLAPI_PLUGIN_PRE_DELETE_FN;
-
- if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry) == 0) &&
- plugin_entry &&
- (plugin_type = slapi_entry_attr_get_charptr(plugin_entry, "nsslapd-plugintype")) &&
- plugin_type && strstr(plugin_type, "betxn")) {
- predel = SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN;
- }
- slapi_ch_free_string(&plugin_type);
-
/* set up csn generator for tombstone */
_usn_csngen = csngen_new(USN_CSNGEN_ID, NULL);
if (NULL == _usn_csngen) {
@@ -177,30 +173,34 @@ static int
usn_bepreop_init(Slapi_PBlock *pb)
{
int rc = 0;
- Slapi_Entry *plugin_entry = NULL;
- char *plugin_type = NULL;
- int preadd = SLAPI_PLUGIN_BE_PRE_ADD_FN;
int premod = SLAPI_PLUGIN_BE_PRE_MODIFY_FN;
int premdn = SLAPI_PLUGIN_BE_PRE_MODRDN_FN;
- int predel = SLAPI_PLUGIN_BE_PRE_DELETE_FN;
- if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry) == 0) &&
- plugin_entry &&
- (plugin_type = slapi_entry_attr_get_charptr(plugin_entry, "nsslapd-plugintype")) &&
- plugin_type && strstr(plugin_type, "betxn")) {
- preadd = SLAPI_PLUGIN_BE_TXN_PRE_ADD_FN;
- premod = SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN;
- premdn = SLAPI_PLUGIN_BE_TXN_PRE_MODRDN_FN;
- predel = SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN;
+ /* usn_bepreop functions are called at BE_PRE_OP timing,
+ * not at BE_TXN_PREOP */
+ /* modify/modrdn updates mods which is evaluated before the
+ * transaction start */
+ if ((slapi_pblock_set(pb, premod, (void *)usn_bepreop_modify) != 0) ||
+ (slapi_pblock_set(pb, premdn, (void *)usn_bepreop_modify) != 0)) {
+ slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
+ "usn_bepreop_init: failed to register bepreop plugin\n");
+ rc = -1;
}
- slapi_ch_free_string(&plugin_type);
- if (slapi_pblock_set(pb, preadd, (void *)usn_bepreop_add) != 0 ||
- slapi_pblock_set(pb, predel, (void *)usn_bepreop_delete) != 0 ||
- slapi_pblock_set(pb, premod, (void *)usn_bepreop_modify) != 0 ||
- slapi_pblock_set(pb, premdn, (void *)usn_bepreop_modify) != 0) {
+ return rc;
+}
+
+static int
+usn_betxnpreop_init(Slapi_PBlock *pb)
+{
+ int rc = 0;
+ int preadd = SLAPI_PLUGIN_BE_TXN_PRE_ADD_FN;
+ int predel = SLAPI_PLUGIN_BE_TXN_PRE_DELETE_TOMBSTONE_FN;
+
+ if ((slapi_pblock_set(pb, preadd, (void *)usn_betxnpreop_add) != 0) ||
+ (slapi_pblock_set(pb, predel, (void *)usn_betxnpreop_delete) != 0)) {
slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
- "usn_bepreop_init: failed to register bepreop plugin\n");
+ "usn_betxnpreop_init: failed to register betxnpreop plugin\n");
rc = -1;
}
@@ -220,7 +220,8 @@ usn_bepostop_init(Slapi_PBlock *pb)
if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry) == 0) &&
plugin_entry &&
- (plugin_type = slapi_entry_attr_get_charptr(plugin_entry, "nsslapd-plugintype")) &&
+ (plugin_type = slapi_entry_attr_get_charptr(plugin_entry,
+ "nsslapd-plugintype")) &&
plugin_type && strstr(plugin_type, "betxn")) {
postadd = SLAPI_PLUGIN_BE_TXN_POST_ADD_FN;
postmod = SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN;
@@ -229,12 +230,12 @@ usn_bepostop_init(Slapi_PBlock *pb)
}
slapi_ch_free_string(&plugin_type);
- if (slapi_pblock_set(pb, postadd, (void *)usn_bepostop) != 0 ||
- slapi_pblock_set(pb, postdel, (void *)usn_bepostop_delete) != 0 ||
- slapi_pblock_set(pb, postmod, (void *)usn_bepostop_modify) != 0 ||
- slapi_pblock_set(pb, postmdn, (void *)usn_bepostop) != 0) {
+ if ((slapi_pblock_set(pb, postadd, (void *)usn_bepostop) != 0) ||
+ (slapi_pblock_set(pb, postdel, (void *)usn_bepostop_delete) != 0) ||
+ (slapi_pblock_set(pb, postmod, (void *)usn_bepostop_modify) != 0) ||
+ (slapi_pblock_set(pb, postmdn, (void *)usn_bepostop) != 0)) {
slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
- "usn_bepostop_init: failed to register bepostop plugin\n");
+ "usn_bepostop_init: failed to register bepostop plugin\n");
rc = -1;
}
@@ -356,10 +357,8 @@ bail:
return rc;
}
-#define KEEP_PREV_USN 1
-
static void
-_usn_add_next_usn(Slapi_Entry *e, Slapi_Backend *be, int flags)
+_usn_add_next_usn(Slapi_Entry *e, Slapi_Backend *be)
{
struct berval usn_berval = {0};
Slapi_Attr* attr = NULL;
@@ -383,14 +382,6 @@ _usn_add_next_usn(Slapi_Entry *e, Slapi_Backend *be, int flags)
slapi_value_free(&usn_value);
} else { /* ENTRYUSN exists; replace it */
struct berval *new_bvals[2];
- struct berval **prev_values = NULL;
- if (KEEP_PREV_USN == flags) {
- if (0 == slapi_attr_get_bervals_copy(attr, &prev_values)) {
- slapi_entry_add_values(e,
- SLAPI_ATTR_ENTRYUSN_PREV, prev_values);
- ber_bvecfree(prev_values);
- }
- }
new_bvals[0] = &usn_berval;
new_bvals[1] = NULL;
slapi_entry_attr_replace(e, SLAPI_ATTR_ENTRYUSN, new_bvals);
@@ -440,17 +431,17 @@ _usn_mod_next_usn(LDAPMod ***mods, Slapi_Backend *be)
}
/*
- * usn_bepreop_add - add next USN to the entry to be added
+ * usn_betxnpreop_add - add next USN to the entry to be added
*/
static int
-usn_bepreop_add(Slapi_PBlock *pb)
+usn_betxnpreop_add(Slapi_PBlock *pb)
{
Slapi_Entry *e = NULL;
Slapi_Backend *be = NULL;
int rc = LDAP_SUCCESS;
slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
- "--> usn_bepreop_add\n");
+ "--> usn_betxnpreop_add\n");
/* add next USN to the entry; "be" contains the usn counter */
slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e);
@@ -463,26 +454,26 @@ usn_bepreop_add(Slapi_PBlock *pb)
rc = LDAP_PARAM_ERROR;
goto bail;
}
- _usn_add_next_usn(e, be, 0);
+ _usn_add_next_usn(e, be);
bail:
slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
- "<-- usn_bepreop_add\n");
+ "<-- usn_betxnpreop_add\n");
return rc;
}
/*
- * usn_bepreop_delete -- add/replace next USN to the entry
+ * usn_betxnpreop_delete -- add/replace next USN to the entry
* bepreop_delete is not called if the entry is tombstone
*/
static int
-usn_bepreop_delete(Slapi_PBlock *pb)
+usn_betxnpreop_delete(Slapi_PBlock *pb)
{
Slapi_Entry *e = NULL;
Slapi_Backend *be = NULL;
int rc = LDAP_SUCCESS;
slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
- "--> usn_bepreop_delete\n");
+ "--> usn_betxnpreop_delete\n");
/* add next USN to the entry; "be" contains the usn counter */
slapi_pblock_get(pb, SLAPI_DELETE_BEPREOP_ENTRY, &e);
@@ -499,12 +490,11 @@ usn_bepreop_delete(Slapi_PBlock *pb)
Slapi_Operation *op = NULL;
slapi_pblock_get(pb, SLAPI_OPERATION, &op);
slapi_operation_set_flag(op, OP_FLAG_TOMBSTONE_ENTRY);
- } else {
- _usn_add_next_usn(e, be, KEEP_PREV_USN);
}
+ _usn_add_next_usn(e, be);
bail:
slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
- "<-- usn_bepreop_delete\n");
+ "<-- usn_betxnpreop_delete\n");
return rc;
}
@@ -591,7 +581,7 @@ usn_bepostop_modify (Slapi_PBlock *pb)
for (i = 0; mods && mods[i]; i++) {
if (0 == strcasecmp(mods[i]->mod_type, SLAPI_ATTR_ENTRYUSN)) {
if (mods[i]->mod_op & LDAP_MOD_IGNORE) {
- slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
"usn_bepostop_mod: MOD_IGNORE detected\n");
goto bail; /* conflict occurred.
skip incrementing the counter. */
@@ -623,22 +613,20 @@ 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) {
- 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;
}
@@ -771,5 +759,5 @@ usn_rootdse_search(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter,
int
usn_is_started()
{
- return g_plugin_started;
+ return g_plugin_started;
}
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
index fff93c9..569ad0b 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
@@ -95,7 +95,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
entry_address *addr;
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;
int opreturn = 0;
@@ -107,6 +106,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
slapi_pblock_get( pb, SLAPI_TXN, (void**)&parent_txn );
slapi_pblock_get( pb, SLAPI_OPERATION, &operation );
slapi_pblock_get( pb, SLAPI_IS_REPLICATED_OPERATION, &is_replicated_operation );
+ slapi_pblock_get( pb, SLAPI_DELETE_BEPREOP_ENTRY, &orig_entry );
/* sdn needs to be initialized before "goto *_return */
slapi_sdn_init(&sdn);
@@ -196,10 +196,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)
{
@@ -215,14 +211,15 @@ ldbm_back_delete( Slapi_PBlock *pb )
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;
}
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
- rc = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_DELETE_FN);
+ /* set entry in case be-preop plugins need to work on it (e.g., USN) */
+ slapi_pblock_set( pb, SLAPI_DELETE_BEPREOP_ENTRY, e->ep_entry );
+ rc = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_DELETE_FN);
if (rc == -1)
{
/*
@@ -233,7 +230,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
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 );
slapi_pblock_get( pb, SLAPI_PLUGIN_OPRETURN, &opreturn );
if (!opreturn) {
slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &rc );
@@ -246,8 +242,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).
@@ -380,7 +374,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
slapi_pblock_set ( pb, SLAPI_DELETE_GLUE_PARENT_ENTRY,
slapi_entry_dup (parent_modify_c.new_entry->ep_entry) );
}
- }
+ }
}
slapi_sdn_done(&parentsdn);
@@ -436,21 +430,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
operation_get_csn(operation));
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) ;
- }
- }
-
/* 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? */
}
@@ -522,10 +501,14 @@ ldbm_back_delete( Slapi_PBlock *pb )
/* stash the transaction */
slapi_pblock_set(pb, SLAPI_TXN, txn.back_txn_txn);
- /* call the transaction pre delete plugins just after creating the transaction */
- if ((retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN))) {
- LDAPDebug1Arg( LDAP_DEBUG_TRACE, "SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN plugin "
- "returned error code %d\n", retval );
+ /* call the transaction pre delete plugins just after creating
+ * the transaction */
+ slapi_pblock_set( pb, SLAPI_DELETE_BEPREOP_ENTRY, e->ep_entry );
+ retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN);
+ if (retval) {
+ LDAPDebug1Arg( LDAP_DEBUG_TRACE,
+ "SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN plugin "
+ "returned error code %d\n", retval );
if (!ldap_result_code) {
slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
}
@@ -533,13 +516,40 @@ ldbm_back_delete( Slapi_PBlock *pb )
slapi_pblock_get( pb, SLAPI_PLUGIN_OPRETURN, &opreturn );
}
if (!opreturn) {
- slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &retval );
+ slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN,
+ ldap_result_code ?
+ &ldap_result_code : &retval );
}
goto error_return;
}
if(create_tombstone_entry)
{
+
+ slapi_pblock_set( pb, SLAPI_DELETE_BEPREOP_ENTRY,
+ tombstone->ep_entry );
+ rc = plugin_call_plugins(pb,
+ SLAPI_PLUGIN_BE_TXN_PRE_DELETE_TOMBSTONE_FN);
+ if (rc == -1) {
+ /*
+ * Plugin indicated some kind of failure,
+ * or that this Operation became a No-Op.
+ */
+ if (!ldap_result_code) {
+ slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
+ }
+ /* restore original entry so the front-end delete code
+ * can free it */
+ slapi_pblock_get( pb, SLAPI_PLUGIN_OPRETURN, &opreturn );
+ if (!opreturn) {
+ slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN,
+ ldap_result_code ?
+ &ldap_result_code : &rc );
+ }
+ /* retval is -1 */
+ goto error_return;
+ }
+
/*
* The entry is not removed from the disk when we tombstone an
* entry. We change the DN, add objectclass=tombstone, and record
@@ -703,30 +713,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
goto error_return;
}
}
- /* delete a previous value (if it exists) from the entryusn index */
- if (prev_entryusn_str) {
- retval = index_addordel_string(be, SLAPI_ATTR_ENTRYUSN,
- prev_entryusn_str, tombstone->ep_id,
- BE_INDEX_DEL|BE_INDEX_EQUALITY, &txn);
- slapi_ch_free_string(&prev_entryusn_str);
- if (DB_LOCK_DEADLOCK == retval) {
- LDAPDebug( LDAP_DEBUG_ARGS,
- "delete (deleting %s) DB_LOCK_DEADLOCK\n",
- SLAPI_ATTR_ENTRYUSN, 0, 0 );
- /* Retry txn */
- continue;
- }
- if (0 != retval) {
- LDAPDebug( LDAP_DEBUG_TRACE,
- "delete (deleting %s) failed, err=%d %s\n",
- SLAPI_ATTR_ENTRYUSN, retval,
- (msg = dblayer_strerror( retval )) ? msg : "" );
- if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
- DEL_SET_ERROR(ldap_result_code,
- LDAP_OPERATIONS_ERROR, retry_count);
- goto error_return;
- }
- }
if (entryrdn_get_switch()) /* subtree-rename: on */
{
Slapi_Attr *attr;
@@ -1111,6 +1097,7 @@ error_return:
}
common_return:
+ slapi_pblock_set( pb, SLAPI_DELETE_BEPREOP_ENTRY, orig_entry );
if (tombstone_in_cache)
{
CACHE_RETURN( &inst->inst_cache, &tombstone );
@@ -1127,17 +1114,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 */
diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c
index 4b54403..76c031a 100644
--- a/ldap/servers/slapd/pblock.c
+++ b/ldap/servers/slapd/pblock.c
@@ -1087,6 +1087,12 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
}
(*(IFP *)value) = pblock->pb_plugin->plg_betxnpredelete;
break;
+ case SLAPI_PLUGIN_BE_TXN_PRE_DELETE_TOMBSTONE_FN:
+ if (pblock->pb_plugin->plg_type != SLAPI_PLUGIN_BETXNPREOPERATION) {
+ return( -1 );
+ }
+ (*(IFP *)value) = pblock->pb_plugin->plg_betxnpredeletetombstone;
+ break;
/* backend post txn operation plugin */
case SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN:
@@ -2666,6 +2672,12 @@ slapi_pblock_set( Slapi_PBlock *pblock, int arg, void *value )
}
pblock->pb_plugin->plg_betxnpredelete = (IFP) value;
break;
+ case SLAPI_PLUGIN_BE_TXN_PRE_DELETE_TOMBSTONE_FN:
+ if (pblock->pb_plugin->plg_type != SLAPI_PLUGIN_BETXNPREOPERATION) {
+ return( -1 );
+ }
+ pblock->pb_plugin->plg_betxnpredeletetombstone = (IFP) value;
+ break;
/* backend postoperation plugin - called just before committing transaction */
case SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN:
diff --git a/ldap/servers/slapd/plugin.c b/ldap/servers/slapd/plugin.c
index 4c8e8bd..1585779 100644
--- a/ldap/servers/slapd/plugin.c
+++ b/ldap/servers/slapd/plugin.c
@@ -375,6 +375,7 @@ plugin_call_plugins( Slapi_PBlock *pb, int whichfunction )
case SLAPI_PLUGIN_BE_TXN_PRE_MODRDN_FN:
case SLAPI_PLUGIN_BE_TXN_PRE_ADD_FN:
case SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN:
+ case SLAPI_PLUGIN_BE_TXN_PRE_DELETE_TOMBSTONE_FN:
plugin_list_number= PLUGIN_LIST_BETXNPREOPERATION;
do_op = 1; /* always allow backend callbacks (even during startup) */
break;
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 669e304..54a921e 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -971,6 +971,7 @@ struct slapdplugin {
IFP plg_un_bepre_modrdn; /* modrdn */
IFP plg_un_bepre_add; /* add */
IFP plg_un_bepre_delete; /* delete */
+ IFP plg_un_bepre_delete_tombstone; /* tombstone creation */
IFP plg_un_bepre_close; /* close */
IFP plg_un_bepre_backup; /* backup */
} plg_un_bepre;
@@ -1123,11 +1124,13 @@ struct slapdplugin {
IFP plg_un_betxnpre_modrdn; /* modrdn */
IFP plg_un_betxnpre_add; /* add */
IFP plg_un_betxnpre_delete; /* delete */
+ IFP plg_un_betxnpre_delete_tombstone; /* delete tombstone */
} plg_un_betxnpre;
#define plg_betxnpremodify plg_un.plg_un_betxnpre.plg_un_betxnpre_modify
#define plg_betxnpremodrdn plg_un.plg_un_betxnpre.plg_un_betxnpre_modrdn
#define plg_betxnpreadd plg_un.plg_un_betxnpre.plg_un_betxnpre_add
#define plg_betxnpredelete plg_un.plg_un_betxnpre.plg_un_betxnpre_delete
+#define plg_betxnpredeletetombstone plg_un.plg_un_betxnpre.plg_un_betxnpre_delete_tombstone
/* backend txn post-operation plugin structure */
struct plg_un_betxnpost_operation {
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index fa4892d..bef2356 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -378,7 +378,6 @@ NSPR_API(PRUint32) PR_fprintf(struct PRFileDesc* fd, const char *fmt, ...)
#define SLAPI_ATTR_VALUE_PARENT_UNIQUEID "nsParentUniqueID"
#define SLAPI_ATTR_NSCP_ENTRYDN "nscpEntryDN"
#define SLAPI_ATTR_ENTRYUSN "entryusn"
-#define SLAPI_ATTR_ENTRYUSN_PREV "preventryusn"
#define SLAPI_ATTR_ENTRYDN "entrydn"
@@ -6302,6 +6301,7 @@ typedef struct slapi_plugindesc {
#define SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN 461
#define SLAPI_PLUGIN_BE_TXN_PRE_MODRDN_FN 462
#define SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN 463
+#define SLAPI_PLUGIN_BE_TXN_PRE_DELETE_TOMBSTONE_FN 464
/* postoperation plugin functions */
#define SLAPI_PLUGIN_POST_BIND_FN 501
11 years, 1 month
Branch '389-ds-base-1.2.10' - ldap/servers
by Richard Allen Megginson
ldap/servers/slapd/back-ldbm/idl_new.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
New commits:
commit 5d45dd8de06aaee3e0a52c85fa5b3e18febd7a27
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Fri Apr 20 20:15:21 2012 -0600
Ticket #347 - IPA dirsvr seg-fault during system longevity test
https://fedorahosted.org/389/ticket/347
Resolves: Ticket 347
Bug Description: IPA dirsvr seg-fault during system longevity test
Reviewed by: nhosoi, mreynolds (Thanks!)
Branch: master
Fix Description: Somehow the DB_MULTIPLE_NEXT pointer is being set to
an invalid value (-5). This causes the next iteration to return memory
that points to before the stack buffer, causing a seg fault. Valid
values for the pointer are > -1. The value -1 is used as the list terminator
value. The code that constructs the buffer is in the libdb function
__bam_bulk in bt_cursor.c. The fix is to check for a value < -1,
assume the page or value has been deleted out from under us, and do
a dbc->get to get the next buffer full, if any. The code also needs to
check for duplicate IDs being returned. In the failure case described
above, it is possible that the last ID returned in the multiple buffer is
the first ID in the next buffer. In that case, we want to skip the ID that
was already added to the IDL.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
diff --git a/ldap/servers/slapd/back-ldbm/idl_new.c b/ldap/servers/slapd/back-ldbm/idl_new.c
index d62511c..9cd3daf 100644
--- a/ldap/servers/slapd/back-ldbm/idl_new.c
+++ b/ldap/servers/slapd/back-ldbm/idl_new.c
@@ -242,6 +242,7 @@ IDList * idl_new_fetch(
/* Iterate over the duplicates, amassing them into an IDL */
#ifdef DB_USE_BULK_FETCH
for (;;) {
+ ID lastid = 0;
DB_MULTIPLE_INIT(ptr, &data);
@@ -250,6 +251,13 @@ IDList * idl_new_fetch(
if (dataret.data == NULL) break;
if (ptr == NULL) break;
+ if (*(int32_t *)ptr < -1) {
+ LDAPDebug1Arg(LDAP_DEBUG_TRACE, "DB_MULTIPLE buffer is corrupt; "
+ "next offset [%d] is less than zero\n",
+ *(int32_t *)ptr);
+ /* retry the read */
+ break;
+ }
if (dataret.size != sizeof(ID)) {
LDAPDebug(LDAP_DEBUG_ANY, "database index is corrupt; "
"key %s has a data item with the wrong size (%d)\n",
@@ -257,7 +265,14 @@ IDList * idl_new_fetch(
goto error;
}
memcpy(&id, dataret.data, sizeof(ID));
-
+ if (id == lastid) { /* dup */
+ LDAPDebug1Arg(LDAP_DEBUG_TRACE, "Detedted duplicate id "
+ "%d due to DB_MULTIPLE error - skipping\n",
+ id);
+ continue; /* get next one */
+ }
+ /* note the last id read to check for dups */
+ lastid = id;
/* we got another ID, add it to our IDL */
idl_rc = idl_append_extend(&idl, id);
if (idl_rc) {
11 years, 1 month