ldap/servers
by Noriko Hosoi
ldap/servers/slapd/abandon.c | 2
ldap/servers/slapd/connection.c | 4 -
ldap/servers/slapd/daemon.c | 2
ldap/servers/slapd/pagedresults.c | 130 +++++++++++++++++++-------------------
ldap/servers/slapd/proto-slap.h | 8 +-
5 files changed, 74 insertions(+), 72 deletions(-)
New commits:
commit c19bb9dd1e95ee98a53a06f3d7eefb4dce5bc0ef
Author: Noriko Hosoi <nhosoi(a)totoro.usersys.redhat.com>
Date: Fri Oct 5 17:56:22 2012 -0700
Bug 863576 - Dirsrv deadlock locking up IPA
https://bugzilla.redhat.com/show_bug.cgi?id=863576
Bug Description: Abandon of a Simple Paged Results request causes
the self deadlock. When abandoning a simple paged result request,
the mutex for the connection object c_mutex is locked in do_abandon.
But to free a pagedresult massage id, pagedresults_free_one_msgid
called from do_abandon tries to acquire lock on c_mutex again.
The NSPR lock function PR_Lock is not self re-entrant. Thus the
server hangs there due to the self-deadlock.
Fix Description: This patch is removing to call PR_Lock(c_mutex)
in pagedresults_free_one_msgid and renamed it to pagedresults_free_
one_msgid_nolock. To maintain the consistency, "_nolock" is added
to other pagedresults apis which do not call PR_Lock in it.
Also, stricter locking on c_mutex is being added to pagedresults_
parse_control_value to protect the pagedresults related field in
the connection object.
diff --git a/ldap/servers/slapd/abandon.c b/ldap/servers/slapd/abandon.c
index 4f00da9..094ae95 100644
--- a/ldap/servers/slapd/abandon.c
+++ b/ldap/servers/slapd/abandon.c
@@ -153,7 +153,7 @@ do_abandon( Slapi_PBlock *pb )
}
if ( op_is_pagedresults(o) ) {
- if ( 0 == pagedresults_free_one_msgid(pb->pb_conn, id) ) {
+ if ( 0 == pagedresults_free_one_msgid_nolock(pb->pb_conn, id) ) {
slapi_log_access( LDAP_DEBUG_STATS, "conn=%" NSPRIu64
" op=%d ABANDON targetop=Simple Paged Results\n",
pb->pb_conn->c_connid, pb->pb_op->o_opid );
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
index 9e43104..a3b1df5 100644
--- a/ldap/servers/slapd/connection.c
+++ b/ldap/servers/slapd/connection.c
@@ -2094,7 +2094,7 @@ void connection_enter_leave_turbo(Connection *conn, int current_turbo_flag, int
PR_Lock(conn->c_mutex);
/* We can already be in turbo mode, or not */
current_mode = current_turbo_flag;
- if (pagedresults_in_use(conn)) {
+ if (pagedresults_in_use_nolock(conn)) {
/* PAGED_RESULTS does not need turbo mode */
new_mode = 0;
} else if (conn->c_private->operation_rate == 0) {
@@ -2780,7 +2780,7 @@ disconnect_server_nomutex( Connection *conn, PRUint64 opconnid, int opid, PRErro
connection_abandon_operations( conn );
/* needed here to ensure simple paged results timeout properly and
* don't impact subsequent ops */
- pagedresults_reset_timedout(conn);
+ pagedresults_reset_timedout_nolock(conn);
if (! config_check_referral_mode()) {
/*
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index 0d3d81f..62a52fc 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -1695,7 +1695,7 @@ setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps
{
int add_fd = 1;
/* check timeout for PAGED RESULTS */
- if (pagedresults_is_timedout(c))
+ if (pagedresults_is_timedout_nolock(c))
{
/* Exceeded the timelimit; disconnect the client */
disconnect_server_nomutex(c, c->c_connid, -1,
diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c
index ea7de14..d445c06 100644
--- a/ldap/servers/slapd/pagedresults.c
+++ b/ldap/servers/slapd/pagedresults.c
@@ -64,6 +64,7 @@ pagedresults_parse_control_value( Slapi_PBlock *pb,
struct berval cookie = {0};
Connection *conn = pb->pb_conn;
Operation *op = pb->pb_op;
+ BerElement *ber = NULL;
LDAPDebug0Args(LDAP_DEBUG_TRACE, "--> pagedresults_parse_control_value\n");
if ( NULL == conn || NULL == op || NULL == pagesize || NULL == index ) {
@@ -76,70 +77,71 @@ pagedresults_parse_control_value( Slapi_PBlock *pb,
if ( psbvp->bv_len == 0 || psbvp->bv_val == NULL )
{
- rc = LDAP_PROTOCOL_ERROR;
+ LDAPDebug0Args(LDAP_DEBUG_ANY,
+ "<-- pagedresults_parse_control_value: no control value\n");
+ return LDAP_PROTOCOL_ERROR;
}
- else
+ ber = ber_init( psbvp );
+ if ( ber == NULL )
{
- BerElement *ber = ber_init( psbvp );
- if ( ber == NULL )
- {
- rc = LDAP_OPERATIONS_ERROR;
- }
- else
- {
- if ( ber_scanf( ber, "{io}", pagesize, &cookie ) == LBER_ERROR )
- {
- rc = LDAP_PROTOCOL_ERROR;
+ LDAPDebug0Args(LDAP_DEBUG_ANY,
+ "<-- pagedresults_parse_control_value: no control value\n");
+ return LDAP_PROTOCOL_ERROR;
+ }
+ if ( ber_scanf( ber, "{io}", pagesize, &cookie ) == LBER_ERROR )
+ {
+ LDAPDebug0Args(LDAP_DEBUG_ANY,
+ "<-- pagedresults_parse_control_value: corrupted control value\n");
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ PR_Lock(conn->c_mutex);
+ /* the ber encoding is no longer needed */
+ ber_free(ber, 1);
+ if ( cookie.bv_len <= 0 ) {
+ int i;
+ int maxlen;
+ /* first time? */
+ maxlen = conn->c_pagedresults.prl_maxlen;
+ if (conn->c_pagedresults.prl_count == maxlen) {
+ if (0 == maxlen) { /* first time */
+ conn->c_pagedresults.prl_maxlen = 1;
+ conn->c_pagedresults.prl_list =
+ (PagedResults *)slapi_ch_calloc(1,
+ sizeof(PagedResults));
+ } else {
+ /* new max length */
+ conn->c_pagedresults.prl_maxlen *= 2;
+ conn->c_pagedresults.prl_list =
+ (PagedResults *)slapi_ch_realloc(
+ (char *)conn->c_pagedresults.prl_list,
+ sizeof(PagedResults) *
+ conn->c_pagedresults.prl_maxlen);
+ /* initialze newly allocated area */
+ memset(conn->c_pagedresults.prl_list + maxlen, '\0',
+ sizeof(PagedResults) * maxlen);
}
- /* the ber encoding is no longer needed */
- ber_free(ber, 1);
- if ( cookie.bv_len <= 0 ) {
- int i;
- int maxlen;
- /* first time? */
- PR_Lock(conn->c_mutex);
- maxlen = conn->c_pagedresults.prl_maxlen;
- if (conn->c_pagedresults.prl_count == maxlen) {
- if (0 == maxlen) { /* first time */
- conn->c_pagedresults.prl_maxlen = 1;
- conn->c_pagedresults.prl_list =
- (PagedResults *)slapi_ch_calloc(1,
- sizeof(PagedResults));
- } else {
- /* new max length */
- conn->c_pagedresults.prl_maxlen *= 2;
- conn->c_pagedresults.prl_list =
- (PagedResults *)slapi_ch_realloc(
- (char *)conn->c_pagedresults.prl_list,
- sizeof(PagedResults) *
- conn->c_pagedresults.prl_maxlen);
- /* initialze newly allocated area */
- memset(conn->c_pagedresults.prl_list + maxlen, '\0',
- sizeof(PagedResults) * maxlen);
- }
- *index = maxlen; /* the first position in the new area */
- } else {
- for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++) {
- if (!conn->c_pagedresults.prl_list[i].pr_current_be) {
- *index = i;
- break;
- }
- }
+ *index = maxlen; /* the first position in the new area */
+ } else {
+ for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++) {
+ if (!conn->c_pagedresults.prl_list[i].pr_current_be) {
+ *index = i;
+ break;
}
- conn->c_pagedresults.prl_count++;
- PR_Unlock(conn->c_mutex);
- } else {
- /* Repeated paged results request.
- * PagedResults is already allocated. */
- char *ptr = slapi_ch_malloc(cookie.bv_len + 1);
- memcpy(ptr, cookie.bv_val, cookie.bv_len);
- *(ptr+cookie.bv_len) = '\0';
- *index = strtol(ptr, NULL, 10);
- slapi_ch_free_string(&ptr);
}
- slapi_ch_free((void **)&cookie.bv_val);
}
+ conn->c_pagedresults.prl_count++;
+ } else {
+ /* Repeated paged results request.
+ * PagedResults is already allocated. */
+ char *ptr = slapi_ch_malloc(cookie.bv_len + 1);
+ memcpy(ptr, cookie.bv_val, cookie.bv_len);
+ *(ptr+cookie.bv_len) = '\0';
+ *index = strtol(ptr, NULL, 10);
+ slapi_ch_free_string(&ptr);
}
+ slapi_ch_free((void **)&cookie.bv_val);
+
if ((*index > -1) && (*index < conn->c_pagedresults.prl_maxlen)) {
/* Need to keep the latest msgid to prepare for the abandon. */
conn->c_pagedresults.prl_list[*index].pr_msgid = op->o_msgid;
@@ -149,6 +151,7 @@ pagedresults_parse_control_value( Slapi_PBlock *pb,
"pagedresults_parse_control_value: invalid cookie: %d\n",
*index);
}
+ PR_Unlock(conn->c_mutex);
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"<-- pagedresults_parse_control_value: idx %d\n", *index);
@@ -261,7 +264,7 @@ pagedresults_free_one( Connection *conn, int index )
}
int
-pagedresults_free_one_msgid( Connection *conn, ber_int_t msgid )
+pagedresults_free_one_msgid_nolock( Connection *conn, ber_int_t msgid )
{
int rc = -1;
int i;
@@ -269,9 +272,9 @@ pagedresults_free_one_msgid( Connection *conn, ber_int_t msgid )
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_free_one: msgid=%d\n", msgid);
if (conn && (msgid > -1)) {
- PR_Lock(conn->c_mutex);
if (conn->c_pagedresults.prl_count <= 0) {
- LDAPDebug2Args(LDAP_DEBUG_TRACE, "pagedresults_free_one_msgid: "
+ LDAPDebug2Args(LDAP_DEBUG_TRACE,
+ "pagedresults_free_one_msgid_nolock: "
"conn=%d paged requests list count is %d\n",
conn->c_connid, conn->c_pagedresults.prl_count);
} else {
@@ -285,7 +288,6 @@ pagedresults_free_one_msgid( Connection *conn, ber_int_t msgid )
}
}
}
- PR_Unlock(conn->c_mutex);
}
LDAPDebug1Arg(LDAP_DEBUG_TRACE, "<-- pagedresults_free_one: %d\n", rc);
@@ -720,7 +722,7 @@ pagedresults_reset_processing(Connection *conn, int index)
/* Are all the paged results requests timed out? */
int
-pagedresults_is_timedout(Connection *conn)
+pagedresults_is_timedout_nolock(Connection *conn)
{
int i;
PagedResults *prp = NULL;
@@ -753,7 +755,7 @@ pagedresults_is_timedout(Connection *conn)
/* reset all timeout */
int
-pagedresults_reset_timedout(Connection *conn)
+pagedresults_reset_timedout_nolock(Connection *conn)
{
int i;
PagedResults *prp = NULL;
@@ -773,7 +775,7 @@ pagedresults_reset_timedout(Connection *conn)
/* paged results requests are in progress. */
int
-pagedresults_in_use(Connection *conn)
+pagedresults_in_use_nolock(Connection *conn)
{
LDAPDebug0Args(LDAP_DEBUG_TRACE, "--> pagedresults_in_use\n");
if (NULL == conn) {
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 55c3a78..905b0f4 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -1427,11 +1427,11 @@ int pagedresults_set_timelimit(Connection *conn, time_t timelimit, int index);
int pagedresults_cleanup(Connection *conn, int needlock);
int pagedresults_check_or_set_processing(Connection *conn, int index);
int pagedresults_reset_processing(Connection *conn, int index);
-int pagedresults_is_timedout(Connection *conn);
-int pagedresults_reset_timedout(Connection *conn);
-int pagedresults_in_use(Connection *conn);
+int pagedresults_is_timedout_nolock(Connection *conn);
+int pagedresults_reset_timedout_nolock(Connection *conn);
+int pagedresults_in_use_nolock(Connection *conn);
int pagedresults_free_one(Connection *conn, int index);
-int pagedresults_free_one_msgid( Connection *conn, ber_int_t msgid );
+int pagedresults_free_one_msgid_nolock( Connection *conn, ber_int_t msgid );
int op_is_pagedresults(Operation *op);
int pagedresults_cleanup_all(Connection *conn, int needlock);
void op_set_pagedresults(Operation *op);
11 years, 6 months
ldap/ldif ldap/servers
by Noriko Hosoi
ldap/ldif/50replication-plugins.ldif | 1
ldap/ldif/template-dse.ldif.in | 18
ldap/ldif/template-pampta.ldif.in | 2
ldap/servers/plugins/cos/cos.c | 110 --
ldap/servers/plugins/cos/cos_cache.c | 75 -
ldap/servers/plugins/cos/cos_cache.h | 1
ldap/servers/plugins/memberof/memberof.c | 46
ldap/servers/plugins/pam_passthru/pam_passthru.h | 1
ldap/servers/plugins/pam_passthru/pam_ptpreop.c | 190 ++--
ldap/servers/plugins/referint/referint.c | 65 +
ldap/servers/plugins/replication/repl5.h | 11
ldap/servers/plugins/replication/repl5_init.c | 178 +++
ldap/servers/plugins/replication/repl5_plugins.c | 155 +++
ldap/servers/plugins/replication/repl5_replica.c | 2
ldap/servers/plugins/replication/repl_extop.c | 1
ldap/servers/plugins/roles/roles_plugin.c | 6
ldap/servers/slapd/back-ldbm/dblayer.c | 124 ++
ldap/servers/slapd/back-ldbm/idl.c | 12
ldap/servers/slapd/back-ldbm/idl_new.c | 45
ldap/servers/slapd/back-ldbm/ldbm_add.c | 830 ++++++++---------
ldap/servers/slapd/back-ldbm/ldbm_delete.c | 629 +++++++------
ldap/servers/slapd/back-ldbm/ldbm_modify.c | 223 ++--
ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 1091 +++++++++++------------
ldap/servers/slapd/back-ldbm/ldif2ldbm.c | 22
ldap/servers/slapd/back-ldbm/proto-back-ldbm.h | 18
ldap/servers/slapd/backend.c | 28
ldap/servers/slapd/dse.c | 49 -
ldap/servers/slapd/entry.c | 40
ldap/servers/slapd/mapping_tree.c | 10
ldap/servers/slapd/pblock.c | 5
ldap/servers/slapd/slapi-plugin.h | 34
31 files changed, 2303 insertions(+), 1719 deletions(-)
New commits:
commit cd48bbda6b93cbe6458f6022ba6ccb15925c7ab8
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Wed Sep 19 15:52:56 2012 -0700
Trac Ticket #351 - use betxn plugins by default
https://fedorahosted.org/389/ticket/351
Trac Ticket #352 - make cos, roles, views betxn aware
https://fedorahosted.org/389/ticket/352
Fix Description:
. Enabled betxn by default on the following plugins:
7-bit check Plugin, Attribute uniqueness Plugin
Auto Membership Plugin, Managed Entries, MemberOf Plugin
Multimaster Replication Plugin, PAM Pass Through Auth Plugin
Referential integrity postoperation Plugin
Roles Plugin, State Change Plugin, USN Plugin
. Exposed backend transaction to plugins:
slapi_back_transaction_begin|commit|abort.
. Backend serial lock is held just before the backend transaction
in the dblayer_txn_begin function and released after it is
committed or aborted in dblayer_txn_commit or abort, respectively.
The transaction begin call has to be before "finding" the backend
entry to avoid the deadlock between the serial lock and the
individual entry cache lock. Thus the transaction begins earlier
than this patch.
. dse: adjusting to the bepost behaviour, put betxn post hook into
"need_be_postop" clause.
. Class of Service Plugin:
+ register cos_postop_init as postoperation only (not betxn).
cos_post_op set in cos_post_init is a wrapper of cos_cache_
change_notify, which does not have any backend operations.
Thus, no need to be in transaction. Rather, if putting it
in the transaction it could cause a deadlock between change_
lock and transaction.
. MemberOf Plugin:
+ If betxn is on, MemberOf post operations are called at the
betxn postop timing, which is aborted if the main operation
fails.
+ When betxn is on, member of operations are in the transaction
as sell as in the backend serial lock. Taking advantage of it,
memberof_lock is not held if betxn is on.
+ MemberOf fixup task uses exposed transaction APIs.
. Multimaster Replication Plugin
+ If betxn is on, Multimaster Replication bepreop operations
are called at the betxn preop timing and bepost operations are
called at the betxn postop timing. Note: since betxn post call-
backs are already declared, each bepost callback is called from
the existing betxn post callbacks (see multimaster_be_betxnpostop_*).
. PAM Pass Through Auth Plugin:
+ If betxn is on, PAM Pass Through pre/post operations are called
at the betxn preop/postop timing, respectivly.
. Referential integrity postoperation Plugin
+ If betxn is on, Referential integrity post operations are called
at the betxn postop timing.
+ When betxn is on, referential integirity post operations are in
the transaction as sell as in the backend serial lock. Taking
advantage of it, referint_lock is not held if betxn is on.
. Miscellaneous
+ cos_cache.h: added '#include "ldaplog.h" and removed copied
LDAPDebug from cos.c and cos_cache.c.
+ cos_cache.c: added missing CR at the end of some error messages.
+ repl5_replica.c: removed (nscpentrydn=*) from searching tombstone
entry filter.
+ entry.c: in addition to "true"|"false", "yes"|"no", and digits,
let slapi_entry_attr_get_bool accept "on"|"off".
+ mapping_tree.c: changed the log level of a warning "Mapping tree
node entry for "" point to an unknown backend" issued in mtn_get_be
to BACKLDBM". This message is logged at the start up time of Class
of Service plugin from the dse hook, which is benign.
diff --git a/ldap/ldif/50replication-plugins.ldif b/ldap/ldif/50replication-plugins.ldif
index af0c46b..0b4924c 100644
--- a/ldap/ldif/50replication-plugins.ldif
+++ b/ldap/ldif/50replication-plugins.ldif
@@ -19,6 +19,7 @@ cn: Multimaster Replication Plugin
nsslapd-pluginpath: libreplication-plugin
nsslapd-plugininitfunc: replication_multimaster_plugin_init
nsslapd-plugintype: object
+nsslapd-pluginbetxn: on
nsslapd-pluginenabled: on
nsslapd-plugin-depends-on-named: ldbm database
nsslapd-plugin-depends-on-named: DES
diff --git a/ldap/ldif/template-dse.ldif.in b/ldap/ldif/template-dse.ldif.in
index c626726..e7837a7 100644
--- a/ldap/ldif/template-dse.ldif.in
+++ b/ldap/ldif/template-dse.ldif.in
@@ -496,7 +496,7 @@ objectclass: extensibleObject
cn: State Change Plugin
nsslapd-pluginpath: libstatechange-plugin
nsslapd-plugininitfunc: statechange_init
-nsslapd-plugintype: postoperation
+nsslapd-plugintype: betxnpostoperation
nsslapd-pluginenabled: on
dn: cn=Roles Plugin,cn=plugins,cn=config
@@ -507,6 +507,7 @@ cn: Roles Plugin
nsslapd-pluginpath: libroles-plugin
nsslapd-plugininitfunc: roles_init
nsslapd-plugintype: object
+nsslapd-pluginbetxn: on
nsslapd-pluginenabled: on
nsslapd-plugin-depends-on-type: database
nsslapd-plugin-depends-on-named: State Change Plugin
@@ -541,7 +542,7 @@ objectClass: extensibleObject
cn: MemberOf Plugin
nsslapd-pluginpath: libmemberof-plugin
nsslapd-plugininitfunc: memberof_postop_init
-nsslapd-plugintype: postoperation
+nsslapd-plugintype: betxnpostoperation
nsslapd-pluginenabled: off
nsslapd-plugin-depends-on-type: database
memberOfGroupAttr: member
@@ -592,7 +593,7 @@ objectclass: extensibleObject
cn: referential integrity postoperation
nsslapd-pluginpath: libreferint-plugin
nsslapd-plugininitfunc: referint_postop_init
-nsslapd-plugintype: postoperation
+nsslapd-plugintype: betxnpostoperation
nsslapd-pluginenabled: off
nsslapd-pluginprecedence: 40
nsslapd-pluginArg0: 0
@@ -611,7 +612,7 @@ objectclass: extensibleObject
cn: attribute uniqueness
nsslapd-pluginpath: libattr-unique-plugin
nsslapd-plugininitfunc: NSUniqueAttr_Init
-nsslapd-plugintype: preoperation
+nsslapd-plugintype: betxnpreoperation
nsslapd-pluginenabled: off
nsslapd-pluginarg0: uid
nsslapd-pluginarg1: %ds_suffix%
@@ -624,7 +625,7 @@ objectclass: extensibleObject
cn: 7-bit check
nsslapd-pluginpath: libattr-unique-plugin
nsslapd-plugininitfunc: NS7bitAttr_Init
-nsslapd-plugintype: preoperation
+nsslapd-plugintype: betxnpreoperation
nsslapd-pluginenabled: on
nsslapd-pluginarg0: uid
nsslapd-pluginarg1: mail
@@ -651,7 +652,7 @@ objectclass: extensibleObject
cn: Auto Membership Plugin
nsslapd-pluginpath: libautomember-plugin
nsslapd-plugininitfunc: automember_init
-nsslapd-plugintype: preoperation
+nsslapd-plugintype: betxnpreoperation
nsslapd-pluginenabled: on
nsslapd-plugin-depends-on-type: database
@@ -697,7 +698,7 @@ objectclass: nsContainer
cn: Linked Attributes
nsslapd-pluginpath: liblinkedattrs-plugin
nsslapd-plugininitfunc: linked_attrs_init
-nsslapd-plugintype: preoperation
+nsslapd-plugintype: betxnpreoperation
nsslapd-pluginenabled: on
nsslapd-plugin-depends-on-type: database
@@ -709,7 +710,7 @@ objectclass: nsContainer
cn: Managed Entries
nsslapd-pluginpath: libmanagedentries-plugin
nsslapd-plugininitfunc: mep_init
-nsslapd-plugintype: preoperation
+nsslapd-plugintype: betxnpreoperation
nsslapd-pluginenabled: on
nsslapd-plugin-depends-on-type: database
@@ -733,6 +734,7 @@ nsslapd-pluginpath: libusn-plugin
nsslapd-plugininitfunc: usn_init
nsslapd-plugintype: object
nsslapd-pluginenabled: off
+nsslapd-pluginbetxn: on
nsslapd-plugin-depends-on-type: database
dn: cn=RootDN Access Control,cn=plugins,cn=config
diff --git a/ldap/ldif/template-pampta.ldif.in b/ldap/ldif/template-pampta.ldif.in
index 10df352..9e8f38b 100644
--- a/ldap/ldif/template-pampta.ldif.in
+++ b/ldap/ldif/template-pampta.ldif.in
@@ -6,7 +6,7 @@ objectclass: pamConfig
cn: PAM Pass Through Auth
nsslapd-pluginpath: libpam-passthru-plugin
nsslapd-plugininitfunc: pam_passthruauth_init
-nsslapd-plugintype: preoperation
+nsslapd-plugintype: betxnpreoperation
nsslapd-pluginenabled: off
nsslapd-pluginLoadGlobal: true
nsslapd-plugin-depends-on-type: database
diff --git a/ldap/servers/plugins/cos/cos.c b/ldap/servers/plugins/cos/cos.c
index 6dfd857..0d76d99 100644
--- a/ldap/servers/plugins/cos/cos.c
+++ b/ldap/servers/plugins/cos/cos.c
@@ -67,45 +67,6 @@
int slapd_log_error_proc( char *subsystem, char *fmt, ... );
-/*** from ldaplog.h ***/
-
-/* edited ldaplog.h for LDAPDebug()*/
-#ifndef _LDAPLOG_H
-#define _LDAPLOG_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define LDAP_DEBUG_TRACE 0x00001 /* 1 */
-#define LDAP_DEBUG_ANY 0x04000 /* 16384 */
-#define LDAP_DEBUG_PLUGIN 0x10000 /* 65536 */
-
-/* debugging stuff */
-# ifdef _WIN32
- extern int *module_ldap_debug;
-# define LDAPDebug( level, fmt, arg1, arg2, arg3 ) \
- { \
- if ( *module_ldap_debug & level ) { \
- slapd_log_error_proc( NULL, fmt, arg1, arg2, arg3 ); \
- } \
- }
-# else /* _WIN32 */
- extern int slapd_ldap_debug;
-# define LDAPDebug( level, fmt, arg1, arg2, arg3 ) \
- { \
- if ( slapd_ldap_debug & level ) { \
- slapd_log_error_proc( NULL, fmt, arg1, arg2, arg3 ); \
- } \
- }
-# endif /* Win32 */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _LDAP_H */
-
/*** end secrets ***/
#define COS_PLUGIN_SUBSYSTEM "cos-plugin" /* used for logging */
@@ -166,34 +127,23 @@ int cos_version()
return COS_VERSION;
}
+/*
+ * cos_postop_init: registering cos_post_op
+ * cos_post_op just calls cos_cache_change_notify, which does not have any
+ * backend operations. Thus, no need to be in transaction. Rather, it is
+ * harmful if putting in the transaction since tring to hold change_lock
+ * inside of transaction would cause a deadlock.
+ */
int
cos_postop_init ( Slapi_PBlock *pb )
{
int rc = 0;
- Slapi_Entry *plugin_entry = NULL;
- char *plugin_type = NULL;
- int postadd = SLAPI_PLUGIN_POST_ADD_FN;
- int postmod = SLAPI_PLUGIN_POST_MODIFY_FN;
- int postmdn = SLAPI_PLUGIN_POST_MODRDN_FN;
- int postdel = SLAPI_PLUGIN_POST_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")) {
- postadd = SLAPI_PLUGIN_BE_TXN_POST_ADD_FN;
- postmod = SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN;
- postmdn = SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN;
- postdel = SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN;
- }
- slapi_ch_free_string(&plugin_type);
- if ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
- SLAPI_PLUGIN_VERSION_01 ) != 0 ||
- slapi_pblock_set(pb, postmod, (void *)cos_post_op ) != 0 ||
- slapi_pblock_set(pb, postmdn, (void *)cos_post_op ) != 0 ||
- slapi_pblock_set(pb, postadd, (void *) cos_post_op ) != 0 ||
- slapi_pblock_set(pb, postdel, (void *) cos_post_op ) != 0 )
+ if ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 ) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_POST_ADD_FN, (void *)cos_post_op ) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_POST_DELETE_FN, (void *)cos_post_op ) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODIFY_FN, (void *)cos_post_op ) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODRDN_FN, (void *)cos_post_op ) != 0 )
{
slapi_log_error( SLAPI_LOG_FATAL, COS_PLUGIN_SUBSYSTEM,
"cos_postop_init: failed to register plugin\n" );
@@ -234,17 +184,9 @@ int cos_init( Slapi_PBlock *pb )
{
int ret = 0;
void * plugin_identity=NULL;
- Slapi_Entry *plugin_entry = NULL;
- int is_betxn = 0;
- const char *plugintype = "postoperation";
LDAPDebug( LDAP_DEBUG_TRACE, "--> cos_init\n",0,0,0);
- 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");
- }
-
/*
** Store the plugin identity for later use.
** Used for internal operations
@@ -254,25 +196,17 @@ int cos_init( Slapi_PBlock *pb )
PR_ASSERT (plugin_identity);
cos_set_plugin_identity(plugin_identity);
- if ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
- SLAPI_PLUGIN_VERSION_01 ) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN,
- (void *) cos_start ) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN,
- (void *) cos_close ) != 0 ||
- slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
- (void *)&pdesc ) != 0 )
+ if ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 ) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN, (void *) cos_start ) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN, (void *) cos_close ) != 0 ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&pdesc ) != 0 )
{
slapi_log_error( SLAPI_LOG_FATAL, COS_PLUGIN_SUBSYSTEM,
"cos_init: failed to register plugin\n" );
ret = -1;
goto bailout;
}
-
- if (is_betxn) {
- plugintype = "betxnpostoperation";
- }
- ret = slapi_register_plugin(plugintype, 1 /* Enabled */,
+ ret = slapi_register_plugin("postoperation", 1 /* Enabled */,
"cos_postop_init", cos_postop_init,
"Class of Service postoperation plugin", NULL,
plugin_identity);
@@ -280,12 +214,10 @@ int cos_init( Slapi_PBlock *pb )
goto bailout;
}
- if (!is_betxn) {
- ret = slapi_register_plugin("internalpostoperation", 1 /* Enabled */,
- "cos_internalpostop_init", cos_internalpostop_init,
- "Class of Service internalpostoperation plugin", NULL,
- plugin_identity);
- }
+ ret = slapi_register_plugin("internalpostoperation", 1 /* Enabled */,
+ "cos_internalpostop_init", cos_internalpostop_init,
+ "Class of Service internalpostoperation plugin", NULL,
+ plugin_identity);
bailout:
LDAPDebug( LDAP_DEBUG_TRACE, "<-- cos_init\n",0,0,0);
diff --git a/ldap/servers/plugins/cos/cos_cache.c b/ldap/servers/plugins/cos/cos_cache.c
index 895154d..fed2aa9 100644
--- a/ldap/servers/plugins/cos/cos_cache.c
+++ b/ldap/servers/plugins/cos/cos_cache.c
@@ -124,49 +124,9 @@ void oc_unlock( void );
struct objclass* g_get_global_oc_nolock();
int slapd_log_error_proc( char *subsystem, char *fmt, ... );
-/*** from ldaplog.h ***/
-
-/* edited ldaplog.h for LDAPDebug()*/
-#ifndef _LDAPLOG_H
-#define _LDAPLOG_H
-
/* defined in cos.c */
void * cos_get_plugin_identity();
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define LDAP_DEBUG_TRACE 0x00001 /* 1 */
-#define LDAP_DEBUG_ANY 0x04000 /* 16384 */
-#define LDAP_DEBUG_PLUGIN 0x10000 /* 65536 */
-
-/* debugging stuff */
-# ifdef _WIN32
- extern int *module_ldap_debug;
-# define LDAPDebug( level, fmt, arg1, arg2, arg3 ) \
- { \
- if ( *module_ldap_debug & level ) { \
- slapd_log_error_proc( NULL, fmt, arg1, arg2, arg3 ); \
- } \
- }
-# else /* _WIN32 */
- extern int slapd_ldap_debug;
-# define LDAPDebug( level, fmt, arg1, arg2, arg3 ) \
- { \
- if ( slapd_ldap_debug & level ) { \
- slapd_log_error_proc( NULL, fmt, arg1, arg2, arg3 ); \
- } \
- }
-# endif /* Win32 */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _LDAP_H */
-
/*** end secrets ***/
#define COS_PLUGIN_SUBSYSTEM "cos-plugin" /* used for logging */
@@ -3331,16 +3291,17 @@ void cos_cache_change_notify(Slapi_PBlock *pb)
LDAPDebug( LDAP_DEBUG_TRACE, "--> cos_cache_change_notify\n",0,0,0);
- /* Don't update local cache when remote entries */
- /* are updated. */
+ /* Don't update local cache when remote entries are updated. */
slapi_pblock_get( pb, SLAPI_BACKEND, &be );
- if ( ( be!=NULL ) && (slapi_be_is_flag_set(be,SLAPI_BE_FLAG_REMOTE_DATA)))
+ if ((be && (slapi_be_is_flag_set(be,SLAPI_BE_FLAG_REMOTE_DATA))) ||
+ (NULL == be)) {
goto bail;
+ }
/* need to work out if a cache rebuild is necessary */
- if(slapi_pblock_get( pb, SLAPI_TARGET_SDN, &sdn ))
- {
- LDAPDebug( LDAP_DEBUG_ANY, "cos_cache_change_notify: failed to get dn of changed entry",0,0,0);
+ if(slapi_pblock_get( pb, SLAPI_TARGET_SDN, &sdn )) {
+ LDAPDebug0Args(LDAP_DEBUG_ANY, "cos_cache_change_notify: "
+ "failed to get dn of changed entry\n");
goto bail;
}
dn = slapi_sdn_get_dn(sdn);
@@ -3394,9 +3355,8 @@ void cos_cache_change_notify(Slapi_PBlock *pb)
* stays lean in the face of errors.
*/
if( !do_update && cos_cache_template_index_bsearch(dn)) {
- LDAPDebug( LDAP_DEBUG_PLUGIN, "cos_cache_change_notify:"
- "updating due to indirect template change(%s)\n",
- dn,0,0);
+ LDAPDebug1Arg(LDAP_DEBUG_PLUGIN, "cos_cache_change_notify: "
+ "updating due to indirect template change(%s)\n", dn);
do_update = 1;
}
@@ -3591,30 +3551,29 @@ void cos_cache_backend_state_change(void *handle, char *be_name,
* returns non-zero: entry is cos significant (note does not detect indirect
* template entries).
* 0 : entry is not cos significant.
-*/
+ */
static int cos_cache_entry_is_cos_related( Slapi_Entry *e) {
int rc = 0;
Slapi_Attr *pObjclasses = NULL;
if ( e == NULL ) {
- LDAPDebug( LDAP_DEBUG_ANY, "cos_cache_change_notify:"
- "modified entry is NULL--updating cache just in case!",
- 0,0,0);
+ LDAPDebug0Args(LDAP_DEBUG_ANY, "cos_cache_change_notify: "
+ "modified entry is NULL--updating cache just in case\n");
rc = 1;
} else {
if(slapi_entry_attr_find( e, "objectclass", &pObjclasses ))
{
- LDAPDebug( LDAP_DEBUG_ANY, "cos_cache_change_notify:"
- " failed to get objectclass from %s",
- slapi_entry_get_dn(e),0,0);
+ LDAPDebug1Arg(LDAP_DEBUG_ANY, "cos_cache_change_notify: "
+ " failed to get objectclass from %s\n",
+ slapi_entry_get_dn(e));
rc = 0;
} else {
Slapi_Value *val = NULL;
- int index = 0;
- char *pObj;
+ int index = 0;
+ char *pObj;
/* check out the object classes to see if this was a cosDefinition */
diff --git a/ldap/servers/plugins/cos/cos_cache.h b/ldap/servers/plugins/cos/cos_cache.h
index 5e6105f..2bcaee1 100644
--- a/ldap/servers/plugins/cos/cos_cache.h
+++ b/ldap/servers/plugins/cos/cos_cache.h
@@ -40,6 +40,7 @@
# include <config.h>
#endif
+#include "ldaplog.h"
#if !defined( _COS_CACHE_H )
#define _COS_CACHE_H
diff --git a/ldap/servers/plugins/memberof/memberof.c b/ldap/servers/plugins/memberof/memberof.c
index 6943d91..8fcc88c 100644
--- a/ldap/servers/plugins/memberof/memberof.c
+++ b/ldap/servers/plugins/memberof/memberof.c
@@ -78,6 +78,7 @@ static void* _PluginID = NULL;
static PRMonitor *memberof_operation_lock = 0;
MemberOfConfig *qsortConfig = 0;
static int g_plugin_started = 0;
+static int usetxn = 0;
typedef struct _memberofstringll
{
@@ -191,7 +192,6 @@ memberof_postop_init(Slapi_PBlock *pb)
char *memberof_plugin_identity = 0;
Slapi_Entry *plugin_entry = NULL;
char *plugin_type = NULL;
- int usetxn = 0;
int delfn = SLAPI_PLUGIN_POST_DELETE_FN;
int mdnfn = SLAPI_PLUGIN_POST_MODRDN_FN;
int modfn = SLAPI_PLUGIN_POST_MODIFY_FN;
@@ -2248,14 +2248,20 @@ int memberof_qsort_compare(const void *a, const void *b)
val1, val2);
}
+/* betxn: This locking mechanism is necessary to guarantee the memberof
+ * consistency */
void memberof_lock()
{
- PR_EnterMonitor(memberof_operation_lock);
+ if (usetxn) {
+ PR_EnterMonitor(memberof_operation_lock);
+ }
}
void memberof_unlock()
{
- PR_ExitMonitor(memberof_operation_lock);
+ if (usetxn) {
+ PR_ExitMonitor(memberof_operation_lock);
+ }
}
typedef struct _task_data
@@ -2271,6 +2277,7 @@ void memberof_fixup_task_thread(void *arg)
Slapi_Task *task = (Slapi_Task *)arg;
task_data *td = NULL;
int rc = 0;
+ Slapi_PBlock *fixup_pb = NULL;
/* Fetch our task data from the task */
td = (task_data *)slapi_task_get_data(task);
@@ -2280,7 +2287,9 @@ void memberof_fixup_task_thread(void *arg)
slapi_task_begin(task, 1);
slapi_task_log_notice(task, "Memberof task starts (arg: %s) ...\n",
- td->filter_str);
+ td->filter_str);
+ slapi_log_error(SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
+ "Memberof task starts (arg: %s) ...\n", td->filter_str);
/* We need to get the config lock first. Trying to get the
* config lock after we already hold the op lock can cause
@@ -2290,6 +2299,25 @@ void memberof_fixup_task_thread(void *arg)
memberof_copy_config(&configCopy, memberof_get_config());
memberof_unlock_config();
+ if (usetxn) {
+ Slapi_DN *sdn = slapi_sdn_new_dn_byref(td->dn);
+ Slapi_Backend *be = slapi_be_select(sdn);
+ slapi_sdn_free(&sdn);
+ if (be) {
+ fixup_pb = slapi_pblock_new();
+ slapi_pblock_set(fixup_pb, SLAPI_BACKEND, be);
+ rc = slapi_back_transaction_begin(fixup_pb);
+ if (rc) {
+ slapi_log_error(SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
+ "memberof_fixup_task_thread: failed to start transaction\n");
+ }
+ } else {
+ slapi_log_error(SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
+ "memberof_fixup_task_thread: failed to get be backend from %s\n",
+ td->dn);
+ }
+ }
+
/* get the memberOf operation lock */
memberof_lock();
@@ -2299,11 +2327,21 @@ void memberof_fixup_task_thread(void *arg)
/* release the memberOf operation lock */
memberof_unlock();
+ if (usetxn && fixup_pb) {
+ if (rc) { /* failes */
+ slapi_back_transaction_abort(fixup_pb);
+ } else {
+ slapi_back_transaction_commit(fixup_pb);
+ }
+ slapi_pblock_destroy(fixup_pb);
+ }
memberof_free_config(&configCopy);
slapi_task_log_notice(task, "Memberof task finished.");
slapi_task_log_status(task, "Memberof task finished.");
slapi_task_inc_progress(task);
+ slapi_log_error(SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
+ "Memberof task finished (arg: %s) ...\n", td->filter_str);
/* this will queue the destruction of the task */
slapi_task_finish(task, rc);
diff --git a/ldap/servers/plugins/pam_passthru/pam_passthru.h b/ldap/servers/plugins/pam_passthru/pam_passthru.h
index c565fcb..7075b48 100644
--- a/ldap/servers/plugins/pam_passthru/pam_passthru.h
+++ b/ldap/servers/plugins/pam_passthru/pam_passthru.h
@@ -63,6 +63,7 @@
*/
#define PAM_PASSTHRU_PLUGIN_SUBSYSTEM "pam_passthru-plugin" /* for logging */
#define PAM_PASSTHRU_INT_POSTOP_DESC "PAM Passthru internal postop plugin"
+#define PAM_PASSTHRU_PREOP_DESC "PAM Passthru preop plugin"
#define PAM_PASSTHRU_POSTOP_DESC "PAM Passthru postop plugin"
#define PAM_PASSTHRU_ASSERT( expr ) PR_ASSERT( expr )
diff --git a/ldap/servers/plugins/pam_passthru/pam_ptpreop.c b/ldap/servers/plugins/pam_passthru/pam_ptpreop.c
index 687d24c..7d9ff8b 100644
--- a/ldap/servers/plugins/pam_passthru/pam_ptpreop.c
+++ b/ldap/servers/plugins/pam_passthru/pam_ptpreop.c
@@ -73,6 +73,7 @@ static int pam_passthru_modrdn_preop(Slapi_PBlock *pb);
static int pam_passthru_postop(Slapi_PBlock *pb);
static int pam_passthru_internal_postop_init(Slapi_PBlock *pb);
static int pam_passthru_postop_init(Slapi_PBlock *pb);
+static int pam_passthru_preop_init(Slapi_PBlock *pb);
/*
** Plugin identity mgmt
@@ -111,6 +112,13 @@ int
pam_passthruauth_init( Slapi_PBlock *pb )
{
int status = 0;
+ Slapi_Entry *plugin_entry = NULL;
+ char *plugin_type = NULL;
+ int is_betxn = 0;
+ int preadd = SLAPI_PLUGIN_PRE_ADD_FN;
+ int premod = SLAPI_PLUGIN_PRE_MODIFY_FN;
+ int predel = SLAPI_PLUGIN_PRE_DELETE_FN;
+ int premdn = SLAPI_PLUGIN_PRE_MODRDN_FN;
PAM_PASSTHRU_ASSERT( pb != NULL );
@@ -120,47 +128,89 @@ pam_passthruauth_init( Slapi_PBlock *pb )
slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &pam_passthruauth_plugin_identity);
PR_ASSERT (pam_passthruauth_plugin_identity);
- if ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
- (void *)SLAPI_PLUGIN_VERSION_01 ) != 0
- || slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
- (void *)&pdesc ) != 0
- || slapi_pblock_set( pb, SLAPI_PLUGIN_START_FN,
- (void *)pam_passthru_bindpreop_start ) != 0
- || slapi_pblock_set( pb, SLAPI_PLUGIN_PRE_BIND_FN,
- (void *)pam_passthru_bindpreop ) != 0
- || slapi_pblock_set( pb, SLAPI_PLUGIN_PRE_ADD_FN,
- (void *)pam_passthru_add_preop ) != 0
- || slapi_pblock_set( pb, SLAPI_PLUGIN_PRE_MODIFY_FN,
- (void *)pam_passthru_mod_preop ) != 0
- || slapi_pblock_set( pb, SLAPI_PLUGIN_PRE_DELETE_FN,
- (void *)pam_passthru_del_preop ) != 0
- || slapi_pblock_set( pb, SLAPI_PLUGIN_PRE_MODRDN_FN,
- (void *)pam_passthru_modrdn_preop ) != 0
- || slapi_pblock_set( pb, SLAPI_PLUGIN_CLOSE_FN,
- (void *)pam_passthru_bindpreop_close ) != 0 ) {
- slapi_log_error( SLAPI_LOG_FATAL, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
- "pam_passthruauth_init failed\n" );
- status = -1;
- goto bail;
+ 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")) {
+ is_betxn = 1;
+ preadd = SLAPI_PLUGIN_BE_TXN_PRE_ADD_FN;
+ premod = SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN;
+ predel = SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN;
+ premdn = SLAPI_PLUGIN_BE_TXN_PRE_MODRDN_FN;
}
+ slapi_ch_free_string(&plugin_type);
+
+ if (is_betxn) {
+ if ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
+ (void *)SLAPI_PLUGIN_VERSION_01 ) ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&pdesc ) ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_START_FN,
+ (void *)pam_passthru_bindpreop_start ) ||
+ slapi_pblock_set( pb, preadd, (void *)pam_passthru_add_preop ) ||
+ slapi_pblock_set( pb, premod, (void *)pam_passthru_mod_preop ) ||
+ slapi_pblock_set( pb, predel, (void *)pam_passthru_del_preop ) ||
+ slapi_pblock_set( pb, premdn, (void *)pam_passthru_modrdn_preop )) {
+ slapi_log_error( SLAPI_LOG_FATAL, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
+ "pam_passthruauth_init failed\n");
+ status = -1;
+ goto bail;
+ }
- /* Register internal postop functions. */
- if (slapi_register_plugin("internalpostoperation", /* op type */
- 1, /* Enabled */
- "pam_passthruauth_init", /* this function desc */
- pam_passthru_internal_postop_init, /* init func */
- PAM_PASSTHRU_INT_POSTOP_DESC, /* plugin desc */
- NULL, /* ? */
- pam_passthruauth_plugin_identity /* access control */
- )) {
- slapi_log_error(SLAPI_LOG_FATAL, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
- "pam_passthruauth_init: failed to register plugin\n");
- status = -1;
- goto bail;
+ /* Register preop functions for the betxn enabled case */
+ if (slapi_register_plugin("preoperation", /* op type */
+ 1, /* Enabled */
+ "pam_passthruauth_init", /* this function desc */
+ pam_passthru_preop_init, /* init func for pre op */
+ PAM_PASSTHRU_PREOP_DESC, /* plugin desc */
+ NULL, /* ? */
+ pam_passthruauth_plugin_identity /* access control */
+ )) {
+ slapi_log_error(SLAPI_LOG_FATAL, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
+ "pam_passthruauth_init: "
+ "failed to register preop plugin\n");
+ status = -1;
+ goto bail;
+ }
+ } else {
+ if ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
+ (void *)SLAPI_PLUGIN_VERSION_01 ) ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&pdesc ) ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_START_FN,
+ (void *)pam_passthru_bindpreop_start ) ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_PRE_BIND_FN,
+ (void *)pam_passthru_bindpreop ) ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_CLOSE_FN,
+ (void *)pam_passthru_bindpreop_close ) ||
+ slapi_pblock_set( pb, preadd, (void *)pam_passthru_add_preop ) ||
+ slapi_pblock_set( pb, premod, (void *)pam_passthru_mod_preop ) ||
+ slapi_pblock_set( pb, predel, (void *)pam_passthru_del_preop ) ||
+ slapi_pblock_set( pb, premdn, (void *)pam_passthru_modrdn_preop )) {
+ slapi_log_error( SLAPI_LOG_FATAL, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
+ "pam_passthruauth_init failed\n");
+ status = -1;
+ goto bail;
+ }
+ /* Register internal postop functions. */
+ /* If betxn is enabled, internal op is a part of betxn */
+ if (slapi_register_plugin("internalpostoperation", /* op type */
+ 1, /* Enabled */
+ "pam_passthruauth_init", /* this function desc */
+ pam_passthru_internal_postop_init, /* init func */
+ PAM_PASSTHRU_INT_POSTOP_DESC, /* plugin desc */
+ NULL, /* ? */
+ pam_passthruauth_plugin_identity /* access control */
+ )) {
+ slapi_log_error(SLAPI_LOG_FATAL, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
+ "pam_passthruauth_init: "
+ "failed to register internal postop plugin\n");
+ status = -1;
+ goto bail;
+ }
}
/* Register postop functions */
- if (slapi_register_plugin("postoperation", /* op type */
+ if (slapi_register_plugin(is_betxn ? "postoperation" : "betxnpostoperation", /* op type */
1, /* Enabled */
"pam_passthruauth_init", /* this function desc */
pam_passthru_postop_init, /* init func for post op */
@@ -169,7 +219,9 @@ pam_passthruauth_init( Slapi_PBlock *pb )
pam_passthruauth_plugin_identity /* access control */
)) {
slapi_log_error(SLAPI_LOG_FATAL, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
- "pam_passthruauth_init: failed to register plugin\n");
+ "pam_passthruauth_init: "
+ "failed to register (%s) plugin\n",
+ is_betxn ? "postoperation" : "betxnpostoperation");
status = -1;
goto bail;
}
@@ -181,6 +233,24 @@ pam_passthruauth_init( Slapi_PBlock *pb )
return status;
}
+/*
+ * Only if betxn is on, register just pre bind and close as perop operation.
+ * The other preops (add/del/mod/mdn) are registered as betxn pre ops.
+ */
+static int
+pam_passthru_preop_init(Slapi_PBlock *pb)
+{
+ int status = 0;
+ if ( slapi_pblock_set( pb, SLAPI_PLUGIN_PRE_BIND_FN,
+ (void *)pam_passthru_bindpreop ) ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_CLOSE_FN, (void *)pam_passthru_bindpreop_close )) {
+ slapi_log_error( SLAPI_LOG_FATAL, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
+ "pam_passthruauth_preop_init failed\n");
+ status = -1;
+ }
+ return status;
+}
+
static int
pam_passthru_internal_postop_init(Slapi_PBlock *pb)
{
@@ -210,21 +280,37 @@ static int
pam_passthru_postop_init(Slapi_PBlock *pb)
{
int status = 0;
-
- if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION,
- SLAPI_PLUGIN_VERSION_01) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION,
- (void *) &pdesc) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_POST_ADD_FN,
- (void *) pam_passthru_postop) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_POST_DELETE_FN,
- (void *) pam_passthru_postop) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODIFY_FN,
- (void *) pam_passthru_postop) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODRDN_FN,
- (void *) pam_passthru_postop) != 0) {
+ Slapi_Entry *plugin_entry = NULL;
+ char *plugin_type = NULL;
+ int is_betxn = 0;
+ int postadd = SLAPI_PLUGIN_POST_ADD_FN;
+ int postmod = SLAPI_PLUGIN_POST_MODIFY_FN;
+ int postmdn = SLAPI_PLUGIN_POST_MODRDN_FN;
+ int postdel = SLAPI_PLUGIN_POST_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")) {
+ postadd = SLAPI_PLUGIN_BE_TXN_POST_ADD_FN;
+ postmod = SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN;
+ postmdn = SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN;
+ postdel = SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN;
+ is_betxn = 1;
+ }
+ slapi_ch_free_string(&plugin_type);
+
+ if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01) ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *) &pdesc) ||
+ slapi_pblock_set(pb, postadd, (void *) pam_passthru_postop) ||
+ slapi_pblock_set(pb, postdel, (void *) pam_passthru_postop) ||
+ slapi_pblock_set(pb, postmod, (void *) pam_passthru_postop) ||
+ slapi_pblock_set(pb, postmdn, (void *) pam_passthru_postop) ) {
slapi_log_error(SLAPI_LOG_FATAL, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
- "pam_passthru_postop_init: failed to register plugin\n");
+ "pam_passthru_postop_init: "
+ "failed to register (%s) plugin\n",
+ is_betxn ? "betxn postop" : "postop");
status = -1;
}
@@ -329,7 +415,7 @@ pam_passthru_bindpreop_close( Slapi_PBlock *pb )
PAM_PASSTHRU_ASSERT( pb != NULL );
slapi_log_error( SLAPI_LOG_TRACE, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
- "=> pam_passthru_bindpreop_close\n" );
+ "=> pam_passthru_bindpreop_close\n" );
if (!g_pam_plugin_started) {
goto done;
diff --git a/ldap/servers/plugins/referint/referint.c b/ldap/servers/plugins/referint/referint.c
index b219b6a..beb5f9f 100644
--- a/ldap/servers/plugins/referint/referint.c
+++ b/ldap/servers/plugins/referint/referint.c
@@ -79,20 +79,22 @@ int update_integrity(char **argv, Slapi_DN *sDN, char *newrDN, Slapi_DN *newsupe
int GetNextLine(char *dest, int size_dest, PRFileDesc *stream);
int my_fgetc(PRFileDesc *stream);
void referint_thread_func(void *arg);
-void writeintegritylog(Slapi_PBlock *pb, char *logfilename, Slapi_DN *sdn, char *newrdn,
- Slapi_DN *newsuperior, Slapi_DN *requestorsdn);
+void writeintegritylog(Slapi_PBlock *pb, char *logfilename, Slapi_DN *sdn, char *newrdn, Slapi_DN *newsuperior, Slapi_DN *requestorsdn);
/* global thread control stuff */
static PRLock *referint_mutex = NULL;
static PRThread *referint_tid = NULL;
static PRLock *keeprunning_mutex = NULL;
static PRCondVar *keeprunning_cv = NULL;
-int keeprunning = 0;
+static int keeprunning = 0;
+static int refint_started = 0;
static Slapi_PluginDesc pdesc = { "referint", VENDOR, DS_PACKAGE_VERSION, "referential integrity plugin" };
static int allow_repl = 0;
static void* referint_plugin_identity = NULL;
+static int use_txn = 0;
+
#ifdef _WIN32
int *module_ldap_debug = 0;
@@ -102,6 +104,31 @@ void plugin_init_debug_level(int *level_ptr)
}
#endif
+static void
+referint_lock()
+{
+ if (use_txn) { /* no lock if betxn is enabled */
+ return;
+ }
+ if (NULL == referint_mutex) {
+ referint_mutex = PR_NewLock();
+ }
+ if (referint_mutex) {
+ PR_Lock(referint_mutex);
+ }
+}
+
+static void
+referint_unlock()
+{
+ if (use_txn) { /* no lock if betxn is enabled */
+ return;
+ }
+ if (referint_mutex) {
+ PR_Unlock(referint_mutex);
+ }
+}
+
int
referint_postop_init( Slapi_PBlock *pb )
{
@@ -125,6 +152,7 @@ referint_postop_init( Slapi_PBlock *pb )
{
delfn = SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN;
mdnfn = SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN;
+ use_txn = 1;
}
if(plugin_entry){
char *allow_repl_updates;
@@ -164,6 +192,11 @@ referint_postop_del( Slapi_PBlock *pb )
int oprc;
int rc;
+ if (0 == refint_started) {
+ /* not initialized yet */
+ return 0;
+ }
+
if ( slapi_pblock_get( pb, SLAPI_IS_REPLICATED_OPERATION, &isrepop ) != 0 ||
slapi_pblock_get( pb, SLAPI_DELETE_TARGET_SDN, &sdn ) != 0 ||
slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &oprc) != 0)
@@ -705,6 +738,7 @@ update_integrity(char **argv, Slapi_DN *origSDN,
for ( sdn = slapi_get_first_suffix( &node, 0 ); sdn != NULL;
sdn = slapi_get_next_suffix( &node, 0 ))
{
+ Slapi_Backend *be = slapi_be_select(sdn);
search_base = slapi_sdn_get_dn( sdn );
for(i = 3; argv[i] != NULL; i++){
@@ -716,6 +750,7 @@ update_integrity(char **argv, Slapi_DN *origSDN,
/* Use new search API */
slapi_pblock_init(search_result_pb);
+ slapi_pblock_set(search_result_pb, SLAPI_BACKEND, be);
slapi_search_internal_set_pb(search_result_pb, search_base,
LDAP_SCOPE_SUBTREE, filter, attrs, 0 /* attrs only */,
NULL, NULL, referint_plugin_identity, 0);
@@ -837,7 +872,9 @@ int referint_postop_start( Slapi_PBlock *pb)
if (argc >= 1) {
if(atoi(argv[0]) > 0){
/* initialize the cv and lock */
- referint_mutex = PR_NewLock();
+ if (!use_txn && (NULL == referint_mutex)) {
+ referint_mutex = PR_NewLock();
+ }
keeprunning_mutex = PR_NewLock();
keeprunning_cv = PR_NewCondVar(keeprunning_mutex);
keeprunning =1;
@@ -861,6 +898,7 @@ int referint_postop_start( Slapi_PBlock *pb)
return( -1 );
}
+ refint_started = 1;
return(0);
}
@@ -876,6 +914,7 @@ int referint_postop_close( Slapi_PBlock *pb)
PR_Unlock(keeprunning_mutex);
}
+ refint_started = 0;
return(0);
}
@@ -918,9 +957,9 @@ referint_thread_func(void *arg)
}
PR_Unlock(keeprunning_mutex);
- PR_Lock(referint_mutex);
+ referint_lock();
if (( prfd = PR_Open( logfilename, PR_RDONLY, REFERINT_DEFAULT_FILE_MODE )) == NULL ){
- PR_Unlock(referint_mutex);
+ referint_unlock();
/* go back to sleep and wait for this file */
PR_Lock(keeprunning_mutex);
PR_WaitCondVar(keeprunning_cv, PR_SecondsToInterval(delay));
@@ -983,7 +1022,7 @@ referint_thread_func(void *arg)
}
/* unlock and let other writers back at the file */
- PR_Unlock(referint_mutex);
+ referint_unlock();
/* wait on condition here */
PR_Lock(keeprunning_mutex);
@@ -1085,12 +1124,13 @@ writeintegritylog(Slapi_PBlock *pb, char *logfilename, Slapi_DN *sdn,
size_t reqdn_len = 0;
/*
- * Use this lock to protect file data when update integrity is occuring
- * should hopefully not be a big issue on concurrency
+ * Use this lock to protect file data when update integrity is occuring.
+ * If betxn is enabled, this mutex is ignored; transaction itself takes
+ * the role.
*/
- PR_Lock(referint_mutex);
+ referint_lock();
if (( prfd = PR_Open( logfilename, PR_WRONLY | PR_CREATE_FILE | PR_APPEND,
- REFERINT_DEFAULT_FILE_MODE )) == NULL )
+ REFERINT_DEFAULT_FILE_MODE )) == NULL )
{
slapi_log_error( SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM,
"referint_postop could not write integrity log \"%s\" "
@@ -1098,6 +1138,7 @@ writeintegritylog(Slapi_PBlock *pb, char *logfilename, Slapi_DN *sdn,
logfilename, PR_GetError(), slapd_pr_strerror(PR_GetError()) );
PR_Unlock(referint_mutex);
+ referint_unlock();
return;
}
/*
@@ -1155,5 +1196,5 @@ writeintegritylog(Slapi_PBlock *pb, char *logfilename, Slapi_DN *sdn,
" writeintegritylog: failed to close the file descriptor prfd; NSPR error - %d\n",
PR_GetError());
}
- PR_Unlock(referint_mutex);
+ referint_unlock();
}
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index 61b51b0..aa7684c 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -203,9 +203,13 @@ int multimaster_preop_compare (Slapi_PBlock *pb);
int multimaster_bepreop_add (Slapi_PBlock *pb);
int multimaster_bepreop_delete (Slapi_PBlock *pb);
int multimaster_bepreop_modify (Slapi_PBlock *pb);
+int multimaster_bepreop_modrdn (Slapi_PBlock *pb);
+int multimaster_betxnpreop_add (Slapi_PBlock *pb);
+int multimaster_betxnpreop_delete (Slapi_PBlock *pb);
+int multimaster_betxnpreop_modify (Slapi_PBlock *pb);
+int multimaster_betxnpreop_modrdn (Slapi_PBlock *pb);
int replica_ruv_smods_for_op (Slapi_PBlock *pb, char **uniqueid,
Slapi_Mods **smods);
-int multimaster_bepreop_modrdn (Slapi_PBlock *pb);
int multimaster_bepostop_modrdn (Slapi_PBlock *pb);
int multimaster_bepostop_delete (Slapi_PBlock *pb);
int multimaster_postop_bind (Slapi_PBlock *pb);
@@ -217,8 +221,13 @@ int multimaster_betxnpostop_modrdn (Slapi_PBlock *pb);
int multimaster_betxnpostop_delete (Slapi_PBlock *pb);
int multimaster_betxnpostop_add (Slapi_PBlock *pb);
int multimaster_betxnpostop_modify (Slapi_PBlock *pb);
+int multimaster_be_betxnpostop_modrdn (Slapi_PBlock *pb);
+int multimaster_be_betxnpostop_delete (Slapi_PBlock *pb);
+int multimaster_be_betxnpostop_add (Slapi_PBlock *pb);
+int multimaster_be_betxnpostop_modify (Slapi_PBlock *pb);
/* In repl5_init.c */
+extern int repl5_is_betxn;
char* get_thread_private_agmtname ();
void set_thread_private_agmtname (const char *agmtname);
void* get_thread_private_cache ();
diff --git a/ldap/servers/plugins/replication/repl5_init.c b/ldap/servers/plugins/replication/repl5_init.c
index 7a80c6f..59caf4a 100644
--- a/ldap/servers/plugins/replication/repl5_init.c
+++ b/ldap/servers/plugins/replication/repl5_init.c
@@ -227,6 +227,8 @@ get_repl_session_id (Slapi_PBlock *pb, char *idstr, CSN **csn)
}
+/* preop acquires csn generator handle */
+int repl5_is_betxn = 0;
int
multimaster_preop_init( Slapi_PBlock *pb )
{
@@ -248,6 +250,8 @@ multimaster_preop_init( Slapi_PBlock *pb )
return rc;
}
+/* process_postop (core op of post op) frees CSN,
+ * which should be called after betxn is finieshed. */
int
multimaster_postop_init( Slapi_PBlock *pb )
{
@@ -305,6 +309,10 @@ multimaster_internalpostop_init( Slapi_PBlock *pb )
return rc;
}
+/*
+ * bepreop: setting SLAPI_TXN_RUV_MODS_FN, cleanup old stateinfo.
+ * If betxn is off, preop urp is called here, too.
+ */
int
multimaster_bepreop_init( Slapi_PBlock *pb )
{
@@ -326,6 +334,33 @@ multimaster_bepreop_init( Slapi_PBlock *pb )
return rc;
}
+/*
+ * betxnpreop: if betxn is on, call preop urp at betxnpreop.
+ */
+int
+multimaster_betxnpreop_init( Slapi_PBlock *pb )
+{
+ int rc= 0; /* OK */
+
+ if( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 ) != 0 ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&multimasterbepreopdesc ) != 0 ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_BE_TXN_PRE_ADD_FN, (void *) multimaster_betxnpreop_add ) != 0 ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN, (void *) multimaster_betxnpreop_delete ) != 0 ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN, (void *) multimaster_betxnpreop_modify ) != 0 ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_BE_TXN_PRE_MODRDN_FN, (void *) multimaster_betxnpreop_modrdn ) != 0 )
+ {
+ slapi_log_error( SLAPI_LOG_PLUGIN, repl_plugin_name, "multimaster_betxnpreop_init failed\n" );
+ rc= -1;
+ }
+
+ return rc;
+}
+
+/*
+ * This bepostop_init is registered only if plugintype is NOT betxn.
+ * if plugintype is betxn, callbacks are set in each multimaster_betxnpostop
+ * function.
+ */
int
multimaster_bepostop_init( Slapi_PBlock *pb )
{
@@ -345,19 +380,22 @@ multimaster_bepostop_init( Slapi_PBlock *pb )
return rc;
}
+/*
+ * This betxn_bepostop_init is registered only if plugintype is betxn.
+ * Note: other callbacks (add/delete/modify/modrdn) are set in each
+ * multimaster_betxnpostop function.
+ */
int
-multimaster_betxnpostop_init( Slapi_PBlock *pb )
+multimaster_betxn_bepostop_init( Slapi_PBlock *pb )
{
int rc= 0; /* OK */
- if( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 ) != 0 ||
- slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&multimasterbetxnpostopdesc ) != 0 ||
- slapi_pblock_set( pb, SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN, (void *) multimaster_betxnpostop_modrdn ) != 0 ||
- slapi_pblock_set( pb, SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN, (void *) multimaster_betxnpostop_delete ) != 0 ||
- slapi_pblock_set( pb, SLAPI_PLUGIN_BE_TXN_POST_ADD_FN, (void *) multimaster_betxnpostop_add ) != 0 ||
- slapi_pblock_set( pb, SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN, (void *) multimaster_betxnpostop_modify ) != 0 )
+ if( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 ) ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&multimasterbepostopdesc ) ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_BE_POST_OPEN_FN, (void *) changelog5_init ) ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_BE_POST_BACKUP_FN, (void *) cl5DeleteRUV ) )
{
- slapi_log_error( SLAPI_LOG_PLUGIN, repl_plugin_name, "multimaster_betxnpostop_init failed\n" );
+ slapi_log_error( SLAPI_LOG_PLUGIN, repl_plugin_name, "multimaster_betxn_bepostop_init failed\n" );
rc= -1;
}
@@ -365,6 +403,42 @@ multimaster_betxnpostop_init( Slapi_PBlock *pb )
}
int
+multimaster_betxnpostop_init( Slapi_PBlock *pb )
+{
+ int rc = 0; /* OK */
+ void *add_fn;
+ void *del_fn;
+ void *mod_fn;
+ void *mdn_fn;
+
+ if (repl5_is_betxn) {
+ add_fn = multimaster_be_betxnpostop_add;
+ del_fn = multimaster_be_betxnpostop_delete;
+ mod_fn = multimaster_be_betxnpostop_modify;
+ mdn_fn = multimaster_be_betxnpostop_modrdn;
+ } else {
+ add_fn = multimaster_betxnpostop_add;
+ del_fn = multimaster_betxnpostop_delete;
+ mod_fn = multimaster_betxnpostop_modify;
+ mdn_fn = multimaster_betxnpostop_modrdn;
+ }
+
+ if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01) ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION,
+ (void *)&multimasterbetxnpostopdesc) ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_BE_TXN_POST_ADD_FN, add_fn) ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN, del_fn) ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN, mdn_fn) ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN, mod_fn)) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, repl_plugin_name,
+ "multimaster_betxnpostop_init failed\n");
+ rc = -1;
+ }
+
+ return rc;
+}
+
+int
multimaster_start_extop_init( Slapi_PBlock *pb )
{
int rc= 0; /* OK */
@@ -637,9 +711,10 @@ multimaster_started()
*/
int replication_multimaster_plugin_init(Slapi_PBlock *pb)
{
- static int multimaster_initialised= 0;
- int rc= 0; /* OK */
+ static int multimaster_initialised= 0;
+ int rc= 0; /* OK */
void *identity = NULL;
+ Slapi_Entry *plugin_entry = NULL;
slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &identity);
PR_ASSERT (identity);
@@ -654,26 +729,85 @@ int replication_multimaster_plugin_init(Slapi_PBlock *pb)
*/
multimaster_mtnode_extension_init ();
+ if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry) == 0) &&
+ plugin_entry) {
+ repl5_is_betxn = slapi_entry_attr_get_bool(plugin_entry,
+ "nsslapd-pluginbetxn");
+ }
+
if(!multimaster_initialised)
{
/* Initialize extensions */
repl_con_init_ext();
repl_sup_init_ext();
- rc= slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 );
- rc= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&multimasterdesc );
- rc= slapi_pblock_set( pb, SLAPI_PLUGIN_START_FN, (void *) multimaster_start );
- rc= slapi_pblock_set( pb, SLAPI_PLUGIN_CLOSE_FN, (void *) multimaster_stop );
+ rc= slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 );
+ rc= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&multimasterdesc );
+ rc= slapi_pblock_set( pb, SLAPI_PLUGIN_START_FN, (void *) multimaster_start );
+ rc= slapi_pblock_set( pb, SLAPI_PLUGIN_CLOSE_FN, (void *) multimaster_stop );
/* Register the plugin interfaces we implement */
- rc= slapi_register_plugin("preoperation", 1 /* Enabled */, "multimaster_preop_init", multimaster_preop_init, "Multimaster replication preoperation plugin", NULL, identity);
- rc= slapi_register_plugin("postoperation", 1 /* Enabled */, "multimaster_postop_init", multimaster_postop_init, "Multimaster replication postoperation plugin", NULL, identity);
- rc= slapi_register_plugin("bepreoperation", 1 /* Enabled */, "multimaster_bepreop_init", multimaster_bepreop_init, "Multimaster replication bepreoperation plugin", NULL, identity);
- rc= slapi_register_plugin("bepostoperation", 1 /* Enabled */, "multimaster_bepostop_init", multimaster_bepostop_init, "Multimaster replication bepostoperation plugin", NULL, identity);
- rc= slapi_register_plugin("betxnpostoperation", 1 /* Enabled */, "multimaster_betxnpostop_init", multimaster_betxnpostop_init, "Multimaster replication betxnpostoperation plugin", NULL, identity);
- rc= slapi_register_plugin("internalpreoperation", 1 /* Enabled */, "multimaster_internalpreop_init", multimaster_internalpreop_init, "Multimaster replication internal preoperation plugin", NULL, identity);
- rc= slapi_register_plugin("internalpostoperation", 1 /* Enabled */, "multimaster_internalpostop_init", multimaster_internalpostop_init, "Multimaster replication internal postoperation plugin", NULL, identity);
- rc= slapi_register_plugin("extendedop", 1 /* Enabled */, "multimaster_start_extop_init", multimaster_start_extop_init, "Multimaster replication start extended operation plugin", NULL, identity);
+ /* preop acquires csn generator handle */
+ rc = slapi_register_plugin("preoperation", 1 /* Enabled */,
+ "multimaster_preop_init",
+ multimaster_preop_init,
+ "Multimaster replication preoperation plugin",
+ NULL, identity);
+ /* bepreop: setting SLAPI_TXN_RUV_MODS_FN and cleanup old stateinfo
+ * -- should be done before transaction */
+ /* if betxn is off, urp is called at bepreop. */
+ rc = slapi_register_plugin("bepreoperation", 1 /* Enabled */,
+ "multimaster_bepreop_init",
+ multimaster_bepreop_init,
+ "Multimaster replication bepreoperation plugin",
+ NULL, identity);
+ /* is_betxn: be post ops (add/del/mod/mdn) are combined into betxn ops.
+ * no betxn: be post ops are regsitered at bepostoperation. */
+ rc = slapi_register_plugin("betxnpostoperation", 1 /* Enabled */,
+ "multimaster_betxnpostop_init",
+ multimaster_betxnpostop_init,
+ "Multimaster replication betxnpostoperation plugin",
+ NULL, identity);
+ if (repl5_is_betxn) {
+ /* if betxn is on, urp is called at betxnpreop. */
+ rc = slapi_register_plugin("betxnpreoperation", 1 /* Enabled */,
+ "multimaster_betxnpreop_init",
+ multimaster_betxnpreop_init,
+ "Multimaster replication betxnpreoperation plugin",
+ NULL, identity);
+ /* bepostop configures open and backup only (no betxn) */
+ rc = slapi_register_plugin("bepostoperation", 1 /* Enabled */,
+ "multimaster_betxn_bepostop_init",
+ multimaster_betxn_bepostop_init,
+ "Multimaster replication bepostoperation plugin",
+ NULL, identity);
+ } else {
+ /* bepostop configures open and backup only as well as add/del/
+ * mod/mdn bepost ops */
+ rc = slapi_register_plugin("bepostoperation", 1 /* Enabled */,
+ "multimaster_bepostop_init",
+ multimaster_bepostop_init,
+ "Multimaster replication bepostoperation2 plugin",
+ NULL, identity);
+ }
+ /* process_postop (core op of post op) frees CSN,
+ * which should wait until betxn is done. */
+ rc = slapi_register_plugin("postoperation", 1 /* Enabled */,
+ "multimaster_postop_init",
+ multimaster_postop_init,
+ "Multimaster replication postoperation plugin",
+ NULL, identity);
+ rc = slapi_register_plugin("internalpreoperation", 1 /* Enabled */,
+ "multimaster_internalpreop_init",
+ multimaster_internalpreop_init,
+ "Multimaster replication internal preoperation plugin",
+ NULL, identity);
+ rc = slapi_register_plugin("internalpostoperation", 1 /* Enabled */,
+ "multimaster_internalpostop_init",
+ multimaster_internalpostop_init,
+ "Multimaster replication internal postoperation plugin",
+ NULL, identity);
+ rc = slapi_register_plugin("extendedop", 1 /* Enabled */, "multimaster_start_extop_init", multimaster_start_extop_init, "Multimaster replication start extended operation plugin", NULL, identity);
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);
diff --git a/ldap/servers/plugins/replication/repl5_plugins.c b/ldap/servers/plugins/replication/repl5_plugins.c
index c68c9cb..efd7e18 100644
--- a/ldap/servers/plugins/replication/repl5_plugins.c
+++ b/ldap/servers/plugins/replication/repl5_plugins.c
@@ -700,6 +700,7 @@ purge_entry_state_information (Slapi_PBlock *pb)
}
}
+/* pure bepreop's -- should be done before transaction starts */
int
multimaster_bepreop_add (Slapi_PBlock *pb)
{
@@ -716,8 +717,9 @@ multimaster_bepreop_add (Slapi_PBlock *pb)
if (!is_fixup_operation)
{
slapi_pblock_set(pb, SLAPI_TXN_RUV_MODS_FN,
- (void *)replica_ruv_smods_for_op);
- if (is_replicated_operation) {
+ (void *)replica_ruv_smods_for_op);
+ if (!repl5_is_betxn && is_replicated_operation) {
+ /* if is_betxn is on, urp is called at betxn preop */
rc = urp_add_operation(pb);
}
}
@@ -741,8 +743,9 @@ multimaster_bepreop_delete (Slapi_PBlock *pb)
if(!is_fixup_operation)
{
slapi_pblock_set(pb, SLAPI_TXN_RUV_MODS_FN,
- (void *)replica_ruv_smods_for_op);
- if (is_replicated_operation) {
+ (void *)replica_ruv_smods_for_op);
+ if (!repl5_is_betxn && is_replicated_operation) {
+ /* if is_betxn is on, urp is called at betxn preop */
rc = urp_delete_operation(pb);
}
}
@@ -766,8 +769,9 @@ multimaster_bepreop_modify (Slapi_PBlock *pb)
if(!is_fixup_operation)
{
slapi_pblock_set(pb, SLAPI_TXN_RUV_MODS_FN,
- (void *)replica_ruv_smods_for_op);
- if (is_replicated_operation) {
+ (void *)replica_ruv_smods_for_op);
+ if (!repl5_is_betxn && is_replicated_operation) {
+ /* if is_betxn is on, urp is called at betxn preop */
rc = urp_modify_operation(pb);
}
}
@@ -794,8 +798,9 @@ multimaster_bepreop_modrdn (Slapi_PBlock *pb)
if(!is_fixup_operation)
{
slapi_pblock_set(pb, SLAPI_TXN_RUV_MODS_FN,
- (void *)replica_ruv_smods_for_op);
- if (is_replicated_operation) {
+ (void *)replica_ruv_smods_for_op);
+ if (!repl5_is_betxn && is_replicated_operation) {
+ /* if is_betxn is on, urp is called at betxn preop */
rc = urp_modrdn_operation(pb);
}
}
@@ -806,6 +811,99 @@ multimaster_bepreop_modrdn (Slapi_PBlock *pb)
return rc;
}
+/* betxn preop's */
+int
+multimaster_betxnpreop_add (Slapi_PBlock *pb)
+{
+ int rc= 0;
+ Slapi_Operation *op;
+ int is_replicated_operation;
+ int is_fixup_operation;
+
+ slapi_pblock_get(pb, SLAPI_OPERATION, &op);
+ is_replicated_operation= operation_is_flag_set(op,OP_FLAG_REPLICATED);
+ is_fixup_operation= operation_is_flag_set(op,OP_FLAG_REPL_FIXUP);
+
+ /* For replicated operations, apply URP algorithm */
+ if (!is_fixup_operation)
+ {
+ if (is_replicated_operation) {
+ rc = urp_add_operation(pb);
+ }
+ }
+
+ return rc;
+}
+
+int
+multimaster_betxnpreop_delete (Slapi_PBlock *pb)
+{
+ int rc= 0;
+ Slapi_Operation *op;
+ int is_replicated_operation;
+ int is_fixup_operation;
+
+ slapi_pblock_get(pb, SLAPI_OPERATION, &op);
+ is_replicated_operation= operation_is_flag_set(op,OP_FLAG_REPLICATED);
+ is_fixup_operation= operation_is_flag_set(op,OP_FLAG_REPL_FIXUP);
+
+ /* For replicated operations, apply URP algorithm */
+ if(!is_fixup_operation)
+ {
+ if (is_replicated_operation) {
+ rc = urp_delete_operation(pb);
+ }
+ }
+
+ return rc;
+}
+
+int
+multimaster_betxnpreop_modify (Slapi_PBlock *pb)
+{
+ int rc= 0;
+ Slapi_Operation *op;
+ int is_replicated_operation;
+ int is_fixup_operation;
+
+ slapi_pblock_get(pb, SLAPI_OPERATION, &op);
+ is_replicated_operation= operation_is_flag_set(op,OP_FLAG_REPLICATED);
+ is_fixup_operation= operation_is_flag_set(op,OP_FLAG_REPL_FIXUP);
+
+ /* For replicated operations, apply URP algorithm */
+ if(!is_fixup_operation)
+ {
+ if (is_replicated_operation) {
+ rc = urp_modify_operation(pb);
+ }
+ }
+
+ return rc;
+}
+
+int
+multimaster_betxnpreop_modrdn (Slapi_PBlock *pb)
+{
+ int rc= 0;
+ Slapi_Operation *op;
+ int is_replicated_operation;
+ int is_fixup_operation;
+
+ slapi_pblock_get(pb, SLAPI_OPERATION, &op);
+ is_replicated_operation= operation_is_flag_set(op,OP_FLAG_REPLICATED);
+ is_fixup_operation= operation_is_flag_set(op,OP_FLAG_REPL_FIXUP);
+
+ /* For replicated operations, apply URP algorithm */
+ if(!is_fixup_operation)
+ {
+ if (is_replicated_operation) {
+ rc = urp_modrdn_operation(pb);
+ }
+ }
+
+ return rc;
+}
+
int
multimaster_bepostop_modrdn (Slapi_PBlock *pb)
{
@@ -887,6 +985,47 @@ multimaster_betxnpostop_modify (Slapi_PBlock *pb)
return write_changelog_and_ruv(pb);
}
+/* If nsslapd-pluginbetxn is on */
+int
+multimaster_be_betxnpostop_delete (Slapi_PBlock *pb)
+{
+ int rc = 0;
+ /* original betxnpost */
+ rc = write_changelog_and_ruv(pb);
+ /* original bepost */
+ rc |= multimaster_bepostop_delete(pb);
+ return rc;
+}
+
+int
+multimaster_be_betxnpostop_modrdn (Slapi_PBlock *pb)
+{
+ int rc = 0;
+ /* original betxnpost */
+ rc = write_changelog_and_ruv(pb);
+ /* original bepost */
+ rc |= multimaster_bepostop_modrdn(pb);
+ return rc;
+}
+
+int
+multimaster_be_betxnpostop_add (Slapi_PBlock *pb)
+{
+ int rc = 0;
+ /* original betxnpost */
+ rc = write_changelog_and_ruv(pb);
+ return rc;
+}
+
+int
+multimaster_be_betxnpostop_modify (Slapi_PBlock *pb)
+{
+ int rc = 0;
+ /* original betxnpost */
+ rc = write_changelog_and_ruv(pb);
+ return rc;
+}
+
/* Helper functions */
/*
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
index 2b1d958..846881d 100644
--- a/ldap/servers/plugins/replication/repl5_replica.c
+++ b/ldap/servers/plugins/replication/repl5_replica.c
@@ -2829,7 +2829,7 @@ _replica_reap_tombstones(void *arg)
ctrls[2] = NULL;
pb = slapi_pblock_new();
slapi_search_internal_set_pb(pb, slapi_sdn_get_dn(replica->repl_root),
- LDAP_SCOPE_SUBTREE, "(&(objectclass=nstombstone)(nscpentrydn=*))",
+ LDAP_SCOPE_SUBTREE, "(objectclass=nstombstone)",
attrs, 0, ctrls, NULL,
repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0);
diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c
index 1b72dfb..c94ef8f 100644
--- a/ldap/servers/plugins/replication/repl_extop.c
+++ b/ldap/servers/plugins/replication/repl_extop.c
@@ -906,6 +906,7 @@ multimaster_extop_StartNSDS50ReplicationRequest(Slapi_PBlock *pb)
/* remove this code once ticket 374 is fixed */
#ifdef ENABLE_TEST_TICKET_374
+#include <unistd.h>
if (getenv("SLAPD_TEST_TICKET_374") && (opid > 20)) {
int i = 0;
int max = 480 * 5;
diff --git a/ldap/servers/plugins/roles/roles_plugin.c b/ldap/servers/plugins/roles/roles_plugin.c
index eab773c..9db76ca 100644
--- a/ldap/servers/plugins/roles/roles_plugin.c
+++ b/ldap/servers/plugins/roles/roles_plugin.c
@@ -146,7 +146,7 @@ int roles_init( Slapi_PBlock *pb )
void *plugin_identity = NULL;
Slapi_Entry *plugin_entry = NULL;
int is_betxn = 0;
- const char *plugintype = "postoperation";
+ const char *plugin_type = "postoperation";
slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM,
"=> roles_init\n" );
@@ -176,9 +176,9 @@ int roles_init( Slapi_PBlock *pb )
}
if (is_betxn) {
- plugintype = "betxnpostoperation";
+ plugin_type = "betxnpostoperation";
}
- rc = slapi_register_plugin(plugintype, 1 /* Enabled */,
+ rc = slapi_register_plugin(plugin_type, 1 /* Enabled */,
"roles_postop_init", roles_postop_init,
"Roles postoperation plugin", NULL,
plugin_identity);
diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c
index 5452d6b..3a400bc 100644
--- a/ldap/servers/slapd/back-ldbm/dblayer.c
+++ b/ldap/servers/slapd/back-ldbm/dblayer.c
@@ -3425,7 +3425,8 @@ int dblayer_txn_init(struct ldbminfo *li, back_txn *txn)
}
-int dblayer_txn_begin_ext(struct ldbminfo *li, back_txnid parent_txn, back_txn *txn, PRBool use_lock)
+int
+dblayer_txn_begin_ext(struct ldbminfo *li, back_txnid parent_txn, back_txn *txn, PRBool use_lock)
{
int return_value = -1;
dblayer_private *priv = NULL;
@@ -3489,12 +3490,26 @@ int dblayer_txn_begin_ext(struct ldbminfo *li, back_txnid parent_txn, back_txn *
return return_value;
}
-int dblayer_read_txn_begin(struct ldbminfo *li, back_txnid parent_txn, back_txn *txn) {
- return (dblayer_txn_begin_ext(li,parent_txn,txn,PR_FALSE));
+int
+dblayer_read_txn_begin(backend *be, back_txnid parent_txn, back_txn *txn)
+{
+ struct ldbminfo *li = (struct ldbminfo *)be->be_database->plg_private;
+ return (dblayer_txn_begin_ext(li,parent_txn,txn,PR_FALSE));
}
-int dblayer_txn_begin(struct ldbminfo *li, back_txnid parent_txn, back_txn *txn) {
- return (dblayer_txn_begin_ext(li,parent_txn,txn,PR_TRUE));
+int
+dblayer_txn_begin(backend *be, back_txnid parent_txn, back_txn *txn)
+{
+ struct ldbminfo *li = (struct ldbminfo *)be->be_database->plg_private;
+ int rc = 0;
+ if (SERIALLOCK(li)) {
+ dblayer_lock_backend(be);
+ }
+ rc = dblayer_txn_begin_ext(li,parent_txn,txn,PR_TRUE);
+ if (rc && SERIALLOCK(li)) {
+ dblayer_unlock_backend(be);
+ }
+ return rc;
}
@@ -3568,12 +3583,22 @@ int dblayer_txn_commit_ext(struct ldbminfo *li, back_txn *txn, PRBool use_lock)
return return_value;
}
-int dblayer_read_txn_commit(struct ldbminfo *li, back_txn *txn) {
- return(dblayer_txn_commit_ext(li,txn,PR_FALSE));
+int
+dblayer_read_txn_commit(backend *be, back_txn *txn)
+{
+ struct ldbminfo *li = (struct ldbminfo *)be->be_database->plg_private;
+ return(dblayer_txn_commit_ext(li,txn,PR_FALSE));
}
-int dblayer_txn_commit(struct ldbminfo *li, back_txn *txn) {
- return(dblayer_txn_commit_ext(li,txn,PR_TRUE));
+int
+dblayer_txn_commit(backend *be, back_txn *txn)
+{
+ struct ldbminfo *li = (struct ldbminfo *)be->be_database->plg_private;
+ int rc = dblayer_txn_commit_ext(li,txn,PR_TRUE);
+ if (SERIALLOCK(li)) {
+ dblayer_unlock_backend(be);
+ }
+ return rc;
}
int dblayer_txn_abort_ext(struct ldbminfo *li, back_txn *txn, PRBool use_lock)
@@ -3633,14 +3658,41 @@ int dblayer_txn_abort_ext(struct ldbminfo *li, back_txn *txn, PRBool use_lock)
return return_value;
}
-int dblayer_read_txn_abort(struct ldbminfo *li, back_txn *txn){
- return(dblayer_txn_abort_ext(li,txn,PR_FALSE));
+int
+dblayer_read_txn_abort(backend *be, back_txn *txn)
+{
+ struct ldbminfo *li = (struct ldbminfo *)be->be_database->plg_private;
+ return(dblayer_txn_abort_ext(li, txn, PR_FALSE));
+}
+
+int
+dblayer_txn_abort(backend *be, back_txn *txn)
+{
+ struct ldbminfo *li = (struct ldbminfo *)be->be_database->plg_private;
+ int rc = dblayer_txn_abort_ext(li, txn, PR_TRUE);
+ if (SERIALLOCK(li)) {
+ dblayer_unlock_backend(be);
+ }
+ return rc;
+}
+
+int
+dblayer_txn_begin_all(struct ldbminfo *li, back_txnid parent_txn, back_txn *txn)
+{
+ return (dblayer_txn_begin_ext(li,parent_txn,txn,PR_TRUE));
}
-int dblayer_txn_abort(struct ldbminfo *li, back_txn *txn){
- return(dblayer_txn_abort_ext(li,txn,PR_TRUE));
+int
+dblayer_txn_commit_all(struct ldbminfo *li, back_txn *txn)
+{
+ return(dblayer_txn_commit_ext(li, txn, PR_TRUE));
}
+int
+dblayer_txn_abort_all(struct ldbminfo *li, back_txn *txn)
+{
+ return(dblayer_txn_abort_ext(li, txn, PR_TRUE));
+}
size_t dblayer_get_optimal_block_size(struct ldbminfo *li)
{
@@ -4663,15 +4715,27 @@ unsigned long db_strtoul(const char *str, int *err)
int dblayer_plugin_begin(Slapi_PBlock *pb)
{
int return_value = -1;
- struct ldbminfo *li = NULL;
back_txnid parent;
back_txn current;
+ Slapi_Backend *be;
- slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
+ slapi_pblock_get(pb, SLAPI_BACKEND, &be);
slapi_pblock_get( pb, SLAPI_PARENT_TXN, (void**)&parent );
+ if (NULL == be) {
+ Slapi_DN *sdn;
+ slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn);
+ if (NULL == sdn) {
+ return return_value;
+ }
+ be = slapi_be_select(sdn);
+ if (NULL == be) {
+ return return_value;
+ }
+ slapi_pblock_set(pb, SLAPI_BACKEND, be);
+ }
/* call begin, and put the result in the txnid parameter */
- return_value = dblayer_txn_begin(li,parent,¤t);
+ return_value = dblayer_txn_begin(be, parent, ¤t);
if (0 == return_value)
{
@@ -4686,14 +4750,16 @@ int dblayer_plugin_commit(Slapi_PBlock *pb)
{
/* get the txnid and call commit */
int return_value = -1;
- struct ldbminfo *li = NULL;
back_txn current;
+ Slapi_Backend *be;
- slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
+ slapi_pblock_get(pb, SLAPI_BACKEND, &be);
slapi_pblock_get( pb, SLAPI_TXN, (void**)&(current.back_txn_txn) );
+ if (NULL == be) {
+ return return_value;
+ }
- /* call begin, and put the result in the txnid parameter */
- return_value = dblayer_txn_commit(li,¤t);
+ return_value = dblayer_txn_commit(be, ¤t);
return return_value;
}
@@ -4702,7 +4768,19 @@ int dblayer_plugin_commit(Slapi_PBlock *pb)
int dblayer_plugin_abort(Slapi_PBlock *pb)
{
/* get the txnid and call abort */
- return 0;
+ int return_value = -1;
+ back_txn current;
+ Slapi_Backend *be;
+
+ slapi_pblock_get(pb, SLAPI_BACKEND, &be);
+ slapi_pblock_get( pb, SLAPI_TXN, (void**)&(current.back_txn_txn) );
+ if (NULL == be) {
+ return return_value;
+ }
+
+ return_value = dblayer_txn_abort(be, ¤t);
+
+ return return_value;
}
@@ -5847,7 +5925,7 @@ dblayer_backup(struct ldbminfo *li, char *dest_dir, Slapi_Task *task)
/* do a quick checkpoint */
dblayer_force_checkpoint(li);
dblayer_txn_init(li,&txn);
- return_value=dblayer_txn_begin(li,NULL,&txn);
+ return_value = dblayer_txn_begin_all(li, NULL, &txn);
if (return_value) {
LDAPDebug0Args(LDAP_DEBUG_ANY,
"Backup: transaction error\n");
@@ -6087,7 +6165,7 @@ dblayer_backup(struct ldbminfo *li, char *dest_dir, Slapi_Task *task)
bail:
slapi_ch_free((void **)&listA);
slapi_ch_free((void **)&listB);
- dblayer_txn_abort(li,&txn);
+ dblayer_txn_abort_all(li, &txn);
slapi_ch_free_string(&changelogdir);
return return_value;
}
diff --git a/ldap/servers/slapd/back-ldbm/idl.c b/ldap/servers/slapd/back-ldbm/idl.c
index 5d467bd..4227055 100644
--- a/ldap/servers/slapd/back-ldbm/idl.c
+++ b/ldap/servers/slapd/back-ldbm/idl.c
@@ -295,16 +295,16 @@ idl_old_fetch(
dblayer_txn_init(li,&s_txn);
if (NULL != txn)
{
- dblayer_read_txn_begin(li,txn,&s_txn);
+ dblayer_read_txn_begin(be, txn, &s_txn);
}
if ( (idl = idl_fetch_one( li, db, key, s_txn.back_txn_txn, err )) == NULL ) {
- dblayer_read_txn_commit(li,&s_txn);
+ dblayer_read_txn_commit(be, &s_txn);
return( NULL );
}
/* regular block */
if ( ! INDIRECT_BLOCK( idl ) ) {
- dblayer_read_txn_commit(li,&s_txn);
+ dblayer_read_txn_commit(be, &s_txn);
/* make sure we have the current value of highest id */
if ( ALLIDS(idl) ) {
idl_free( idl );
@@ -336,9 +336,9 @@ idl_old_fetch(
if ( (tmp[i] = idl_fetch_one( li, db, &k2, s_txn.back_txn_txn, err )) == NULL ) {
if(*err == DB_LOCK_DEADLOCK) {
- dblayer_read_txn_abort(li,&s_txn);
+ dblayer_read_txn_abort(be, &s_txn);
} else {
- dblayer_read_txn_commit(li,&s_txn);
+ dblayer_read_txn_commit(be, &s_txn);
}
slapi_ch_free((void**)&kstr );
slapi_ch_free((void**)&tmp );
@@ -364,7 +364,7 @@ idl_old_fetch(
}
}
}
- dblayer_read_txn_commit(li,&s_txn);
+ dblayer_read_txn_commit(be, &s_txn);
tmp[i] = NULL;
slapi_ch_free((void**)&kstr );
idl_free( idl );
diff --git a/ldap/servers/slapd/back-ldbm/idl_new.c b/ldap/servers/slapd/back-ldbm/idl_new.c
index 9cd3daf..64ffc9d 100644
--- a/ldap/servers/slapd/back-ldbm/idl_new.c
+++ b/ldap/servers/slapd/back-ldbm/idl_new.c
@@ -174,11 +174,13 @@ IDList * idl_new_fetch(
ID id = 0;
size_t count = 0;
#ifdef DB_USE_BULK_FETCH
- /* beware that a large buffer on the stack might cause a stack overflow on some platforms */
+ /* beware that a large buffer on the stack might cause a stack overflow on some platforms */
char buffer[BULK_FETCH_BUFFER_SIZE];
void *ptr;
DBT dataret;
#endif
+ back_txn s_txn;
+ struct ldbminfo *li = (struct ldbminfo *)be->be_database->plg_private;
if (NEW_IDL_NOOP == *flag_err)
{
@@ -186,6 +188,11 @@ IDList * idl_new_fetch(
return NULL;
}
+ dblayer_txn_init(li, &s_txn);
+ if (txn) {
+ dblayer_read_txn_begin(be, txn, &s_txn);
+ }
+
/* Make a cursor */
ret = db->cursor(db,txn,&cursor,0);
if (0 != ret) {
@@ -286,14 +293,14 @@ IDList * idl_new_fetch(
LDAPDebug(LDAP_DEBUG_TRACE, "bulk fetch buffer nids=%d\n", count, 0, 0);
#if defined(DB_ALLIDS_ON_READ)
- /* enforce the allids read limit */
- if ((NEW_IDL_NO_ALLID != *flag_err) && (NULL != a) &&
- (idl != NULL) && idl_new_exceeds_allidslimit(count, a, allidslimit)) {
- idl->b_nids = 1;
- idl->b_ids[0] = ALLID;
- ret = DB_NOTFOUND; /* fool the code below into thinking that we finished the dups */
- break;
- }
+ /* enforce the allids read limit */
+ if ((NEW_IDL_NO_ALLID != *flag_err) && (NULL != a) &&
+ (idl != NULL) && idl_new_exceeds_allidslimit(count, a, allidslimit)) {
+ idl->b_nids = 1;
+ idl->b_ids[0] = ALLID;
+ ret = DB_NOTFOUND; /* fool the code below into thinking that we finished the dups */
+ break;
+ }
#endif
ret = cursor->c_get(cursor,&key,&data,DB_NEXT_DUP|DB_MULTIPLE);
if (0 != ret) {
@@ -303,7 +310,7 @@ IDList * idl_new_fetch(
#else
for (;;) {
ret = cursor->c_get(cursor,&key,&data,DB_NEXT_DUP);
- count++;
+ count++;
if (0 != ret) {
break;
}
@@ -314,14 +321,14 @@ IDList * idl_new_fetch(
idl_free(idl); idl = NULL;
goto error;
}
-#if defined(DB_ALLIDS_ON_READ)
- /* enforce the allids read limit */
- if ((idl != NULL) && idl_new_exceeds_allidslimit(count, a, allidslimit)) {
- idl->b_nids = 1;
- idl->b_ids[0] = ALLID;
- ret = DB_NOTFOUND; /* fool the code below into thinking that we finished the dups */
- break;
- }
+#if defined(DB_ALLIDS_ON_READ)
+ /* enforce the allids read limit */
+ if ((idl != NULL) && idl_new_exceeds_allidslimit(count, a, allidslimit)) {
+ idl->b_nids = 1;
+ idl->b_ids[0] = ALLID;
+ ret = DB_NOTFOUND; /* fool the code below into thinking that we finished the dups */
+ break;
+ }
#endif
}
#endif
@@ -358,6 +365,7 @@ error:
}
}
}
+ dblayer_read_txn_commit(be, &s_txn);
*flag_err = ret;
return idl;
}
@@ -629,7 +637,6 @@ int idl_new_store_block(
* inserts a list of duplicate keys. In the meantime, we'll
* just do it by brute force.
*/
-
#if defined(DB_ALLIDS_ON_WRITE)
/* allids check on input idl */
if (ALLIDS(idl) || (idl->b_nids > (ID)idl_new_get_allidslimit(a, 0))) {
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c
index 158dc8e..b8989fc 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c
@@ -109,7 +109,6 @@ ldbm_back_add( Slapi_PBlock *pb )
Slapi_DN *sdn = NULL;
Slapi_DN parentsdn;
Slapi_Operation *operation;
- int dblock_acquired= 0;
int is_replicated_operation= 0;
int is_resurect_operation= 0;
int is_tombstone_operation= 0;
@@ -158,12 +157,16 @@ ldbm_back_add( Slapi_PBlock *pb )
* But, this lock is re-enterant for the fixup
* operations that the URP code in the Replication
* plugin generates.
- */
+ *
+ * SERIALLOCK is moved to dblayer_txn_begin along with exposing be
+ * transaction to plugins (see slapi_back_transaction_* APIs).
+ *
if(SERIALLOCK(li) && !is_fixup_operation)
{
dblayer_lock_backend(be);
dblock_acquired= 1;
}
+ */
rc= 0;
@@ -294,405 +297,16 @@ ldbm_back_add( Slapi_PBlock *pb )
* the duration of the old race condition's window of opportunity.
*/
- /*
- * Fetch the parent entry and acquire the cache lock.
- */
- if(have_parent_address(&parentsdn, operation->o_params.p.p_add.parentuniqueid))
- {
- addr.sdn = &parentsdn;
- addr.udn = NULL;
- addr.uniqueid = operation->o_params.p.p_add.parentuniqueid;
- parententry = find_entry2modify_only(pb,be,&addr,&txn);
- if (parententry && parententry->ep_entry) {
- if (!operation->o_params.p.p_add.parentuniqueid){
- /* Set the parentuniqueid now */
- operation->o_params.p.p_add.parentuniqueid = slapi_ch_strdup(slapi_entry_get_uniqueid(parententry->ep_entry));
- }
- if (slapi_sdn_isempty(&parentsdn)) {
- /* Set the parentsdn now */
- slapi_sdn_set_dn_byval(&parentsdn, slapi_entry_get_dn_const(parententry->ep_entry));
- }
- }
- modify_init(&parent_modify_c,parententry);
- }
-
- /* Check if the entry we have been asked to add already exists */
- {
- Slapi_Entry *entry;
- slapi_pblock_get( pb, SLAPI_ADD_EXISTING_DN_ENTRY, &entry);
- if ( entry != NULL )
- {
- /* The entry already exists */
- ldap_result_code= LDAP_ALREADY_EXISTS;
- goto error_return;
- }
- else
- {
- /*
- * did not find the entry - this is good, since we're
- * trying to add it, but we have to check whether the
- * entry we did match has a referral we should return
- * instead. we do this only if managedsait is not on.
- */
- if ( !managedsait && !is_tombstone_operation )
- {
- int err= 0;
- Slapi_DN ancestorsdn;
- struct backentry *ancestorentry;
- slapi_sdn_init(&ancestorsdn);
- ancestorentry= dn2ancestor(pb->pb_backend,sdn,&ancestorsdn,&txn,&err);
- slapi_sdn_done(&ancestorsdn);
- if ( ancestorentry != NULL )
- {
- int sentreferral= check_entry_for_referral(pb, ancestorentry->ep_entry, backentry_get_ndn(ancestorentry), "ldbm_back_add");
- CACHE_RETURN( &inst->inst_cache, &ancestorentry );
- if(sentreferral)
- {
- ldap_result_code= -1; /* The result was sent by check_entry_for_referral */
- goto error_return;
- }
- }
- }
- }
- }
-
- /* no need to check the schema as this is a replication add */
- if(!is_replicated_operation){
- if ((operation_is_flag_set(operation,OP_FLAG_ACTION_SCHEMA_CHECK)) && slapi_entry_schema_check(pb, e) != 0)
- {
- LDAPDebug(LDAP_DEBUG_TRACE, "entry failed schema check\n", 0, 0, 0);
- ldap_result_code = LDAP_OBJECT_CLASS_VIOLATION;
- slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
- goto error_return;
- }
-
- /* Check attribute syntax */
- if (slapi_entry_syntax_check(pb, e, 0) != 0)
- {
- LDAPDebug(LDAP_DEBUG_TRACE, "entry failed syntax check\n", 0, 0, 0);
- ldap_result_code = LDAP_INVALID_SYNTAX;
- slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
- goto error_return;
- }
- }
-
- opcsn = operation_get_csn (operation);
- if(is_resurect_operation)
- {
- char *reason = NULL;
- /*
- * When we resurect a tombstone we must use its UniqueID
- * to find the tombstone entry and lock it down in the cache.
- */
- addr.udn = NULL;
- addr.sdn = NULL;
- addr.uniqueid = (char *)slapi_entry_get_uniqueid(e); /* jcm - cast away const */
- tombstoneentry = find_entry2modify( pb, be, &addr, &txn );
- if ( tombstoneentry==NULL )
- {
- ldap_result_code= -1;
- goto error_return; /* error result sent by find_entry2modify() */
- }
- tombstone_in_cache = 1;
-
- addingentry = backentry_dup( tombstoneentry );
- if ( addingentry==NULL )
- {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
- /*
- * To resurect a tombstone we must fix its DN and remove the
- * parent UniqueID that we stashed in there.
- *
- * The entry comes back to life as a Glue entry, so we add the
- * magic objectclass.
- */
- if (NULL == sdn) {
- LDAPDebug0Args(LDAP_DEBUG_ANY, "ldbm_back_add: Null target dn\n");
- goto error_return;
- }
- dn = slapi_sdn_get_dn(sdn);
- slapi_entry_set_sdn(addingentry->ep_entry, sdn); /* The DN is passed into the entry. */
- /* LPREPL: the DN is normalized...Somehow who should get a not normalized one */
- addingentry->ep_id = slapi_entry_attr_get_ulong(addingentry->ep_entry,"entryid");
- slapi_entry_attr_delete(addingentry->ep_entry, SLAPI_ATTR_VALUE_PARENT_UNIQUEID);
- slapi_entry_delete_string(addingentry->ep_entry, SLAPI_ATTR_OBJECTCLASS, SLAPI_ATTR_VALUE_TOMBSTONE);
- /* Now also remove the nscpEntryDN */
- if (slapi_entry_attr_delete(addingentry->ep_entry, SLAPI_ATTR_NSCP_ENTRYDN) != 0){
- LDAPDebug(LDAP_DEBUG_REPL, "Resurrection of %s - Couldn't remove %s\n", dn, SLAPI_ATTR_NSCP_ENTRYDN, 0);
- }
-
- /* And copy the reason from e */
- reason = slapi_entry_attr_get_charptr(e, "nsds5ReplConflict");
- if (reason) {
- if (!slapi_entry_attr_hasvalue(addingentry->ep_entry, "nsds5ReplConflict", reason)) {
- slapi_entry_add_string(addingentry->ep_entry, "nsds5ReplConflict", reason);
- LDAPDebug(LDAP_DEBUG_REPL, "Resurrection of %s - Added Conflict reason %s\n", dn, reason, 0);
- }
- slapi_ch_free((void **)&reason);
- }
- /* Clear the Tombstone Flag in the entry */
- slapi_entry_clear_flag(addingentry->ep_entry, SLAPI_ENTRY_FLAG_TOMBSTONE);
-
- /* make sure the objectclass
- - does not contain any duplicate values
- - has CSNs for the new values we added
- */
- {
- Slapi_Attr *sa = NULL;
- Slapi_Value sv;
- const struct berval *svbv = NULL;
-
- /* add the extensibleobject objectclass with csn if not present */
- slapi_entry_attr_find(addingentry->ep_entry, SLAPI_ATTR_OBJECTCLASS, &sa);
- slapi_value_init_string(&sv, "extensibleobject");
- svbv = slapi_value_get_berval(&sv);
- if (slapi_attr_value_find(sa, svbv)) { /* not found, so add it */
- if (opcsn) {
- value_update_csn(&sv, CSN_TYPE_VALUE_UPDATED, opcsn);
- }
- slapi_attr_add_value(sa, &sv);
- }
- value_done(&sv);
-
- /* add the glue objectclass with csn if not present */
- slapi_value_init_string(&sv, "glue");
- svbv = slapi_value_get_berval(&sv);
- if (slapi_attr_value_find(sa, svbv)) { /* not found, so add it */
- if (opcsn) {
- value_update_csn(&sv, CSN_TYPE_VALUE_UPDATED, opcsn);
- }
- slapi_attr_add_value(sa, &sv);
- }
- value_done(&sv);
- }
- }
- else
- {
- /*
- * Try to add the entry to the cache, assign it a new entryid
- * and mark it locked. This should only fail if the entry
- * already exists.
- */
- /*
- * next_id will add this id to the list of ids that are pending
- * id2entry indexing.
- */
- addingentry = backentry_init( e );
- if ( ( addingentry->ep_id = next_id( be ) ) >= MAXID ) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "add: maximum ID reached, cannot add entry to "
- "backend '%s'", be->be_name, 0, 0 );
- ldap_result_code = LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
- addingentry_id_assigned= 1;
-
- if (!is_fixup_operation)
- {
- if ( opcsn == NULL && operation->o_csngen_handler )
- {
- /*
- * Current op is a user request. Opcsn will be assigned
- * if the dn is in an updatable replica.
- */
- opcsn = entry_assign_operation_csn ( pb, e, parententry ? parententry->ep_entry : NULL );
- }
- if ( opcsn != NULL )
- {
- entry_set_csn (e, opcsn);
- entry_add_dncsn (e, opcsn);
- entry_add_rdn_csn (e, opcsn);
- entry_set_maxcsn (e, opcsn);
- }
- }
-
- if (is_tombstone_operation)
- {
- /* Directly add the entry as a tombstone */
- /*
- * 1) If the entry has an existing DN, change it to be
- * "nsuniqueid=<uniqueid>, <old dn>"
- * 2) Add the objectclass value "tombstone" and arrange for only
- * that value to be indexed.
- * 3) If the parent entry was found, set the nsparentuniqueid
- * attribute to be the unique id of that parent.
- */
- char *untombstoned_dn = slapi_entry_get_dn(e);
- char *tombstoned_dn = NULL;
- if (NULL == untombstoned_dn)
- {
- untombstoned_dn = "";
- }
- tombstoned_dn = compute_entry_tombstone_dn(untombstoned_dn, addr.uniqueid);
- /*
- * This needs to be done before slapi_entry_set_dn call,
- * because untombstoned_dn is released in slapi_entry_set_dn.
- */
- if (entryrdn_get_switch())
- {
- Slapi_RDN srdn = {0};
- rc = slapi_rdn_init_all_dn(&srdn, tombstoned_dn);
- if (rc) {
- LDAPDebug1Arg( LDAP_DEBUG_TRACE,
- "ldbm_back_add (tombstone_operation): failed to "
- "decompose %s to Slapi_RDN\n", tombstoned_dn);
- } else {
- slapi_entry_set_srdn(e, &srdn);
- slapi_rdn_done(&srdn);
- }
- }
- slapi_entry_set_dn(addingentry->ep_entry, tombstoned_dn);
- /* Work around pb with slapi_entry_add_string (defect 522327)
- * doesn't check duplicate values */
- if (!slapi_entry_attr_hasvalue(addingentry->ep_entry,
- SLAPI_ATTR_OBJECTCLASS, SLAPI_ATTR_VALUE_TOMBSTONE)) {
- slapi_entry_add_string(addingentry->ep_entry,
- SLAPI_ATTR_OBJECTCLASS, SLAPI_ATTR_VALUE_TOMBSTONE);
- slapi_entry_set_flag(addingentry->ep_entry,
- SLAPI_ENTRY_FLAG_TOMBSTONE);
- }
- if (NULL != operation->o_params.p.p_add.parentuniqueid)
- {
- slapi_entry_add_string(addingentry->ep_entry,
- SLAPI_ATTR_VALUE_PARENT_UNIQUEID,
- operation->o_params.p.p_add.parentuniqueid);
- }
- }
- }
-
- /*
- * Get the parent dn and see if the corresponding entry exists.
- * If the parent does not exist, only allow the "root" user to
- * add the entry.
- */
- if ( !slapi_sdn_isempty(&parentsdn) )
- {
- /* This is getting the parent */
- if (NULL == parententry)
- {
- /* Here means that we didn't find the parent */
- int err = 0;
- Slapi_DN ancestorsdn;
- struct backentry *ancestorentry;
-
- LDAPDebug( LDAP_DEBUG_TRACE,
- "parent does not exist, pdn = %s\n",
- slapi_sdn_get_dn(&parentsdn), 0, 0 );
-
- slapi_sdn_init(&ancestorsdn);
- ancestorentry = dn2ancestor(be, &parentsdn, &ancestorsdn, &txn, &err );
- CACHE_RETURN( &inst->inst_cache, &ancestorentry );
-
- ldap_result_code= LDAP_NO_SUCH_OBJECT;
- ldap_result_matcheddn= slapi_ch_strdup((char *)slapi_sdn_get_dn(&ancestorsdn)); /* jcm - cast away const. */
- slapi_sdn_done(&ancestorsdn);
- goto error_return;
- }
- ldap_result_code = plugin_call_acl_plugin (pb, e, NULL, NULL, SLAPI_ACL_ADD,
- ACLPLUGIN_ACCESS_DEFAULT, &errbuf );
- if ( ldap_result_code != LDAP_SUCCESS )
- {
- LDAPDebug( LDAP_DEBUG_TRACE, "no access to parent\n", 0, 0, 0 );
- ldap_result_message= errbuf;
- goto error_return;
- }
- pid = parententry->ep_id;
- }
- else
- { /* no parent */
- if ( !isroot && !is_replicated_operation)
- {
- LDAPDebug( LDAP_DEBUG_TRACE, "no parent & not root\n",
- 0, 0, 0 );
- ldap_result_code= LDAP_INSUFFICIENT_ACCESS;
- goto error_return;
- }
- parententry = NULL;
- pid = 0;
- }
-
- if(is_resurect_operation)
- {
- add_update_entrydn_operational_attributes(addingentry);
- }
- else if (is_tombstone_operation)
- {
- /* Remove the entrydn operational attributes from the addingentry */
- delete_update_entrydn_operational_attributes(addingentry);
- }
- else
- {
- /*
- * add the parentid, entryid and entrydn operational attributes
- */
- add_update_entry_operational_attributes(addingentry, pid);
- }
-
- /* Tentatively add the entry to the cache. We do this after adding any
- * operational attributes to ensure that the cache is sized correctly. */
- if ( cache_add_tentative( &inst->inst_cache, addingentry, NULL )!= 0 )
- {
- LDAPDebug( LDAP_DEBUG_CACHE, "cache_add_tentative concurrency detected\n", 0, 0, 0 );
- ldap_result_code= LDAP_ALREADY_EXISTS;
- goto error_return;
- }
- addingentry_in_cache= 1;
-
- /*
- * Before we add the entry, find out if the syntax of the aci
- * aci attribute values are correct or not. We don't want to
- * the entry if the syntax is incorrect.
- */
- if ( plugin_call_acl_verify_syntax (pb, addingentry->ep_entry, &errbuf) != 0 ) {
- LDAPDebug( LDAP_DEBUG_TRACE, "ACL syntax error\n", 0,0,0);
- ldap_result_code= LDAP_INVALID_SYNTAX;
- ldap_result_message= errbuf;
- goto error_return;
- }
-
- /* Having decided that we're really going to do the operation, let's modify
- the in-memory state of the parent to reflect the new child (update
- subordinate count specifically */
- if (NULL != parententry)
- {
- retval = parent_update_on_childchange(&parent_modify_c,
- PARENTUPDATE_ADD, NULL);
- /* The modify context now contains info needed later */
- if (0 != retval) {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
- parent_found = 1;
- parententry = NULL;
- }
-
- if (!is_ruv && !is_fixup_operation) {
- ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
- if (-1 == ruv_c_init) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm_back_add: ldbm_txn_ruv_modify_context "
- "failed to construct RUV modify context\n",
- 0, 0, 0);
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- retval = 0;
- goto error_return;
- }
- }
-
- if ( (originalentry = backentry_dup(addingentry )) == NULL ) {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
/*
- * So, we believe that no code up till here actually added anything
- * to persistent store. From now on, we're transacted
+ * Use transaction as a backend lock, which should be called
+ * outside of entry lock -- find_entry* / cache_lock_entry
+ * to avoid deadlock.
*/
txn.back_txn_txn = NULL; /* ready to create the child transaction */
for (retry_count = 0; retry_count < RETRY_TIMES; retry_count++) {
if (txn.back_txn_txn && (txn.back_txn_txn != parent_txn)) {
- dblayer_txn_abort(li,&txn);
+ /* Don't release SERIAL LOCK */
+ dblayer_txn_abort_ext(li, &txn, PR_FALSE);
slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
if (addingentry_in_cache) {
@@ -729,7 +343,15 @@ ldbm_back_add( Slapi_PBlock *pb )
}
#endif
}
- retval = dblayer_txn_begin(li,parent_txn,&txn);
+ /* dblayer_txn_begin holds SERIAL lock,
+ * which should be outside of locking the entry (find_entry2modify) */
+ if (0 == retry_count) {
+ /* First time, hold SERIAL LOCK */
+ retval = dblayer_txn_begin(be, parent_txn, &txn);
+ } else {
+ /* Otherwise, no SERIAL LOCK */
+ retval = dblayer_txn_begin_ext(li, parent_txn, &txn, PR_FALSE);
+ }
if (0 != retval) {
if (LDBM_OS_ERR_IS_DISKFULL(retval)) {
disk_full = 1;
@@ -743,7 +365,409 @@ ldbm_back_add( Slapi_PBlock *pb )
/* stash the transaction for plugins */
slapi_pblock_set(pb, SLAPI_TXN, txn.back_txn_txn);
- /* call the transaction pre add plugins just after creating the transaction */
+ if (0 == retry_count) { /* execute just once */
+ /* Nothing in this if crause modifies persistent store.
+ * it's called just once. */
+ /*
+ * Fetch the parent entry and acquire the cache lock.
+ */
+ if(have_parent_address(&parentsdn, operation->o_params.p.p_add.parentuniqueid))
+ {
+ addr.sdn = &parentsdn;
+ addr.udn = NULL;
+ addr.uniqueid = operation->o_params.p.p_add.parentuniqueid;
+ parententry = find_entry2modify_only(pb,be,&addr,&txn);
+ if (parententry && parententry->ep_entry) {
+ if (!operation->o_params.p.p_add.parentuniqueid){
+ /* Set the parentuniqueid now */
+ operation->o_params.p.p_add.parentuniqueid =
+ slapi_ch_strdup(slapi_entry_get_uniqueid(parententry->ep_entry));
+ }
+ if (slapi_sdn_isempty(&parentsdn)) {
+ /* Set the parentsdn now */
+ slapi_sdn_set_dn_byval(&parentsdn, slapi_entry_get_dn_const(parententry->ep_entry));
+ }
+ }
+ modify_init(&parent_modify_c,parententry);
+ }
+
+ /* Check if the entry we have been asked to add already exists */
+ {
+ Slapi_Entry *entry;
+ slapi_pblock_get( pb, SLAPI_ADD_EXISTING_DN_ENTRY, &entry);
+ if ( entry != NULL )
+ {
+ /* The entry already exists */
+ ldap_result_code= LDAP_ALREADY_EXISTS;
+ goto error_return;
+ }
+ else
+ {
+ /*
+ * did not find the entry - this is good, since we're
+ * trying to add it, but we have to check whether the
+ * entry we did match has a referral we should return
+ * instead. we do this only if managedsait is not on.
+ */
+ if ( !managedsait && !is_tombstone_operation )
+ {
+ int err= 0;
+ Slapi_DN ancestorsdn;
+ struct backentry *ancestorentry;
+ slapi_sdn_init(&ancestorsdn);
+ ancestorentry= dn2ancestor(pb->pb_backend,sdn,&ancestorsdn,&txn,&err);
+ slapi_sdn_done(&ancestorsdn);
+ if ( ancestorentry != NULL )
+ {
+ int sentreferral =
+ check_entry_for_referral(pb, ancestorentry->ep_entry,
+ backentry_get_ndn(ancestorentry), "ldbm_back_add");
+ CACHE_RETURN( &inst->inst_cache, &ancestorentry );
+ if(sentreferral)
+ {
+ ldap_result_code= -1; /* The result was sent by check_entry_for_referral */
+ goto error_return;
+ }
+ }
+ }
+ }
+ }
+
+ /* no need to check the schema as this is a replication add */
+ if(!is_replicated_operation){
+ if ((operation_is_flag_set(operation,OP_FLAG_ACTION_SCHEMA_CHECK))
+ && (slapi_entry_schema_check(pb, e) != 0))
+ {
+ LDAPDebug(LDAP_DEBUG_TRACE, "entry failed schema check\n", 0, 0, 0);
+ ldap_result_code = LDAP_OBJECT_CLASS_VIOLATION;
+ slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
+ goto error_return;
+ }
+
+ /* Check attribute syntax */
+ if (slapi_entry_syntax_check(pb, e, 0) != 0)
+ {
+ LDAPDebug(LDAP_DEBUG_TRACE, "entry failed syntax check\n", 0, 0, 0);
+ ldap_result_code = LDAP_INVALID_SYNTAX;
+ slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
+ goto error_return;
+ }
+ }
+
+ opcsn = operation_get_csn (operation);
+ if(is_resurect_operation)
+ {
+ char *reason = NULL;
+ /*
+ * When we resurect a tombstone we must use its UniqueID
+ * to find the tombstone entry and lock it down in the cache.
+ */
+ addr.udn = NULL;
+ addr.sdn = NULL;
+ addr.uniqueid = (char *)slapi_entry_get_uniqueid(e); /* jcm - cast away const */
+ tombstoneentry = find_entry2modify( pb, be, &addr, &txn );
+ if ( tombstoneentry==NULL )
+ {
+ ldap_result_code= -1;
+ goto error_return; /* error result sent by find_entry2modify() */
+ }
+ tombstone_in_cache = 1;
+
+ addingentry = backentry_dup( tombstoneentry );
+ if ( addingentry==NULL )
+ {
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ goto error_return;
+ }
+ /*
+ * To resurect a tombstone we must fix its DN and remove the
+ * parent UniqueID that we stashed in there.
+ *
+ * The entry comes back to life as a Glue entry, so we add the
+ * magic objectclass.
+ */
+ if (NULL == sdn) {
+ LDAPDebug0Args(LDAP_DEBUG_ANY, "ldbm_back_add: Null target dn\n");
+ goto error_return;
+ }
+ dn = slapi_sdn_get_dn(sdn);
+ slapi_entry_set_sdn(addingentry->ep_entry, sdn); /* The DN is passed into the entry. */
+ /* LPREPL: the DN is normalized...Somehow who should get a not normalized one */
+ addingentry->ep_id = slapi_entry_attr_get_ulong(addingentry->ep_entry,"entryid");
+ slapi_entry_attr_delete(addingentry->ep_entry, SLAPI_ATTR_VALUE_PARENT_UNIQUEID);
+ slapi_entry_delete_string(addingentry->ep_entry, SLAPI_ATTR_OBJECTCLASS, SLAPI_ATTR_VALUE_TOMBSTONE);
+ /* Now also remove the nscpEntryDN */
+ if (slapi_entry_attr_delete(addingentry->ep_entry, SLAPI_ATTR_NSCP_ENTRYDN) != 0){
+ LDAPDebug(LDAP_DEBUG_REPL, "Resurrection of %s - Couldn't remove %s\n", dn, SLAPI_ATTR_NSCP_ENTRYDN, 0);
+ }
+
+ /* And copy the reason from e */
+ reason = slapi_entry_attr_get_charptr(e, "nsds5ReplConflict");
+ if (reason) {
+ if (!slapi_entry_attr_hasvalue(addingentry->ep_entry, "nsds5ReplConflict", reason)) {
+ slapi_entry_add_string(addingentry->ep_entry, "nsds5ReplConflict", reason);
+ LDAPDebug(LDAP_DEBUG_REPL, "Resurrection of %s - Added Conflict reason %s\n", dn, reason, 0);
+ }
+ slapi_ch_free((void **)&reason);
+ }
+ /* Clear the Tombstone Flag in the entry */
+ slapi_entry_clear_flag(addingentry->ep_entry, SLAPI_ENTRY_FLAG_TOMBSTONE);
+
+ /* make sure the objectclass
+ - does not contain any duplicate values
+ - has CSNs for the new values we added
+ */
+ {
+ Slapi_Attr *sa = NULL;
+ Slapi_Value sv;
+ const struct berval *svbv = NULL;
+
+ /* add the extensibleobject objectclass with csn if not present */
+ slapi_entry_attr_find(addingentry->ep_entry, SLAPI_ATTR_OBJECTCLASS, &sa);
+ slapi_value_init_string(&sv, "extensibleobject");
+ svbv = slapi_value_get_berval(&sv);
+ if (slapi_attr_value_find(sa, svbv)) { /* not found, so add it */
+ if (opcsn) {
+ value_update_csn(&sv, CSN_TYPE_VALUE_UPDATED, opcsn);
+ }
+ slapi_attr_add_value(sa, &sv);
+ }
+ value_done(&sv);
+
+ /* add the glue objectclass with csn if not present */
+ slapi_value_init_string(&sv, "glue");
+ svbv = slapi_value_get_berval(&sv);
+ if (slapi_attr_value_find(sa, svbv)) { /* not found, so add it */
+ if (opcsn) {
+ value_update_csn(&sv, CSN_TYPE_VALUE_UPDATED, opcsn);
+ }
+ slapi_attr_add_value(sa, &sv);
+ }
+ value_done(&sv);
+ }
+ }
+ else
+ {
+ /*
+ * Try to add the entry to the cache, assign it a new entryid
+ * and mark it locked. This should only fail if the entry
+ * already exists.
+ */
+ /*
+ * next_id will add this id to the list of ids that are pending
+ * id2entry indexing.
+ */
+ addingentry = backentry_init( e );
+ if ( ( addingentry->ep_id = next_id( be ) ) >= MAXID ) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "add: maximum ID reached, cannot add entry to "
+ "backend '%s'", be->be_name, 0, 0 );
+ ldap_result_code = LDAP_OPERATIONS_ERROR;
+ goto error_return;
+ }
+ addingentry_id_assigned= 1;
+
+ if (!is_fixup_operation)
+ {
+ if ( opcsn == NULL && operation->o_csngen_handler )
+ {
+ /*
+ * Current op is a user request. Opcsn will be assigned
+ * if the dn is in an updatable replica.
+ */
+ opcsn = entry_assign_operation_csn ( pb, e, parententry ? parententry->ep_entry : NULL );
+ }
+ if ( opcsn != NULL )
+ {
+ entry_set_csn (e, opcsn);
+ entry_add_dncsn (e, opcsn);
+ entry_add_rdn_csn (e, opcsn);
+ entry_set_maxcsn (e, opcsn);
+ }
+ }
+
+ if (is_tombstone_operation)
+ {
+ /* Directly add the entry as a tombstone */
+ /*
+ * 1) If the entry has an existing DN, change it to be
+ * "nsuniqueid=<uniqueid>, <old dn>"
+ * 2) Add the objectclass value "tombstone" and arrange for only
+ * that value to be indexed.
+ * 3) If the parent entry was found, set the nsparentuniqueid
+ * attribute to be the unique id of that parent.
+ */
+ char *untombstoned_dn = slapi_entry_get_dn(e);
+ char *tombstoned_dn = NULL;
+ if (NULL == untombstoned_dn)
+ {
+ untombstoned_dn = "";
+ }
+ tombstoned_dn = compute_entry_tombstone_dn(untombstoned_dn, addr.uniqueid);
+ /*
+ * This needs to be done before slapi_entry_set_dn call,
+ * because untombstoned_dn is released in slapi_entry_set_dn.
+ */
+ if (entryrdn_get_switch())
+ {
+ Slapi_RDN srdn = {0};
+ rc = slapi_rdn_init_all_dn(&srdn, tombstoned_dn);
+ if (rc) {
+ LDAPDebug1Arg( LDAP_DEBUG_TRACE,
+ "ldbm_back_add (tombstone_operation): failed to "
+ "decompose %s to Slapi_RDN\n", tombstoned_dn);
+ } else {
+ slapi_entry_set_srdn(e, &srdn);
+ slapi_rdn_done(&srdn);
+ }
+ }
+ slapi_entry_set_dn(addingentry->ep_entry, tombstoned_dn);
+ /* Work around pb with slapi_entry_add_string (defect 522327)
+ * doesn't check duplicate values */
+ if (!slapi_entry_attr_hasvalue(addingentry->ep_entry,
+ SLAPI_ATTR_OBJECTCLASS, SLAPI_ATTR_VALUE_TOMBSTONE)) {
+ slapi_entry_add_string(addingentry->ep_entry,
+ SLAPI_ATTR_OBJECTCLASS, SLAPI_ATTR_VALUE_TOMBSTONE);
+ slapi_entry_set_flag(addingentry->ep_entry,
+ SLAPI_ENTRY_FLAG_TOMBSTONE);
+ }
+ if (NULL != operation->o_params.p.p_add.parentuniqueid)
+ {
+ slapi_entry_add_string(addingentry->ep_entry,
+ SLAPI_ATTR_VALUE_PARENT_UNIQUEID,
+ operation->o_params.p.p_add.parentuniqueid);
+ }
+ }
+ }
+
+ /*
+ * Get the parent dn and see if the corresponding entry exists.
+ * If the parent does not exist, only allow the "root" user to
+ * add the entry.
+ */
+ if ( !slapi_sdn_isempty(&parentsdn) )
+ {
+ /* This is getting the parent */
+ if (NULL == parententry)
+ {
+ /* Here means that we didn't find the parent */
+ int err = 0;
+ Slapi_DN ancestorsdn;
+ struct backentry *ancestorentry;
+
+ LDAPDebug( LDAP_DEBUG_TRACE,
+ "parent does not exist, pdn = %s\n",
+ slapi_sdn_get_dn(&parentsdn), 0, 0 );
+
+ slapi_sdn_init(&ancestorsdn);
+ ancestorentry = dn2ancestor(be, &parentsdn, &ancestorsdn, &txn, &err );
+ CACHE_RETURN( &inst->inst_cache, &ancestorentry );
+
+ ldap_result_code= LDAP_NO_SUCH_OBJECT;
+ ldap_result_matcheddn=
+ slapi_ch_strdup((char *)slapi_sdn_get_dn(&ancestorsdn)); /* jcm - cast away const. */
+ slapi_sdn_done(&ancestorsdn);
+ goto error_return;
+ }
+ ldap_result_code = plugin_call_acl_plugin (pb, e, NULL, NULL, SLAPI_ACL_ADD,
+ ACLPLUGIN_ACCESS_DEFAULT, &errbuf );
+ if ( ldap_result_code != LDAP_SUCCESS )
+ {
+ LDAPDebug( LDAP_DEBUG_TRACE, "no access to parent\n", 0, 0, 0 );
+ ldap_result_message= errbuf;
+ goto error_return;
+ }
+ pid = parententry->ep_id;
+ }
+ else
+ { /* no parent */
+ if ( !isroot && !is_replicated_operation)
+ {
+ LDAPDebug( LDAP_DEBUG_TRACE, "no parent & not root\n",
+ 0, 0, 0 );
+ ldap_result_code= LDAP_INSUFFICIENT_ACCESS;
+ goto error_return;
+ }
+ parententry = NULL;
+ pid = 0;
+ }
+
+ if(is_resurect_operation)
+ {
+ add_update_entrydn_operational_attributes(addingentry);
+ }
+ else if (is_tombstone_operation)
+ {
+ /* Remove the entrydn operational attributes from the addingentry */
+ delete_update_entrydn_operational_attributes(addingentry);
+ }
+ else
+ {
+ /*
+ * add the parentid, entryid and entrydn operational attributes
+ */
+ add_update_entry_operational_attributes(addingentry, pid);
+ }
+
+ /* Tentatively add the entry to the cache. We do this after adding any
+ * operational attributes to ensure that the cache is sized correctly. */
+ if ( cache_add_tentative( &inst->inst_cache, addingentry, NULL )!= 0 )
+ {
+ LDAPDebug( LDAP_DEBUG_CACHE, "cache_add_tentative concurrency detected\n", 0, 0, 0 );
+ ldap_result_code= LDAP_ALREADY_EXISTS;
+ goto error_return;
+ }
+ addingentry_in_cache= 1;
+
+ /*
+ * Before we add the entry, find out if the syntax of the aci
+ * aci attribute values are correct or not. We don't want to
+ * the entry if the syntax is incorrect.
+ */
+ if ( plugin_call_acl_verify_syntax (pb, addingentry->ep_entry, &errbuf) != 0 ) {
+ LDAPDebug( LDAP_DEBUG_TRACE, "ACL syntax error\n", 0,0,0);
+ ldap_result_code= LDAP_INVALID_SYNTAX;
+ ldap_result_message= errbuf;
+ goto error_return;
+ }
+
+ /* Having decided that we're really going to do the operation, let's modify
+ the in-memory state of the parent to reflect the new child (update
+ subordinate count specifically */
+ if (NULL != parententry)
+ {
+ retval = parent_update_on_childchange(&parent_modify_c,
+ PARENTUPDATE_ADD, NULL);
+ /* The modify context now contains info needed later */
+ if (0 != retval) {
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ goto error_return;
+ }
+ parent_found = 1;
+ parententry = NULL;
+ }
+
+ if (!is_ruv && !is_fixup_operation) {
+ ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
+ if (-1 == ruv_c_init) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ldbm_back_add: ldbm_txn_ruv_modify_context "
+ "failed to construct RUV modify context\n",
+ 0, 0, 0);
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ retval = 0;
+ goto error_return;
+ }
+ }
+
+ if ( (originalentry = backentry_dup(addingentry )) == NULL ) {
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ goto error_return;
+ }
+ } /* if (0 == retry_count) just once */
+
+ /* call the transaction pre add plugins just after the to-be-added entry
+ * is prepared. */
if ((retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_ADD_FN))) {
int opreturn = 0;
LDAPDebug1Arg( LDAP_DEBUG_TRACE, "SLAPI_PLUGIN_BE_TXN_PRE_ADD_FN plugin "
@@ -1001,7 +1025,8 @@ ldbm_back_add( Slapi_PBlock *pb )
goto error_return;
}
- retval = dblayer_txn_commit(li,&txn);
+ /* Release SERIAL LOCK */
+ retval = dblayer_txn_commit(be, &txn);
/* after commit - txn is no longer valid - replace SLAPI_TXN with parent */
slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
if (0 != retval)
@@ -1078,7 +1103,8 @@ diskfull_return:
}
}
- dblayer_txn_abort(li,&txn); /* abort crashes in case disk full */
+ /* Release SERIAL LOCK */
+ dblayer_txn_abort(be, &txn); /* abort crashes in case disk full */
/* txn is no longer valid - reset the txn pointer to the parent */
slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
}
@@ -1122,10 +1148,6 @@ common_return:
done_with_pblock_entry(pb,SLAPI_ADD_EXISTING_DN_ENTRY);
done_with_pblock_entry(pb,SLAPI_ADD_EXISTING_UNIQUEID_ENTRY);
done_with_pblock_entry(pb,SLAPI_ADD_PARENT_ENTRY);
- if(dblock_acquired)
- {
- dblayer_unlock_backend(be);
- }
if(ldap_result_code!=-1)
{
slapi_send_ldap_result( pb, ldap_result_code, ldap_result_matcheddn, ldap_result_message, 0, NULL );
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
index 73c3658..8cbb2a8 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
@@ -79,7 +79,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
Slapi_DN *sdnp = NULL;
char *e_uniqueid = NULL;
Slapi_DN nscpEntrySDN;
- int dblock_acquired= 0;
Slapi_Operation *operation;
CSN *opcsn = NULL;
int is_fixup_operation = 0;
@@ -155,12 +154,16 @@ ldbm_back_delete( Slapi_PBlock *pb )
* But, this lock is re-enterant for the fixup
* operations that the URP code in the Replication
* plugin generates.
- */
+ *
+ * SERIALLOCK is moved to dblayer_txn_begin along with exposing be
+ * transaction to plugins (see slapi_back_transaction_* APIs).
+ *
if(SERIALLOCK(li) && !operation_is_flag_set(operation,OP_FLAG_REPL_FIXUP))
{
dblayer_lock_backend(be);
dblock_acquired= 1;
}
+ */
/*
* We are about to pass the last abandon test, so from now on we are
@@ -176,281 +179,17 @@ ldbm_back_delete( Slapi_PBlock *pb )
goto error_return;
}
- /* find and lock the entry we are about to modify */
- if ( (e = find_entry2modify( pb, be, addr, &txn )) == NULL )
- {
- ldap_result_code= LDAP_NO_SUCH_OBJECT;
- /* retval is -1 */
- goto error_return; /* error result sent by find_entry2modify() */
- }
- e_in_cache = 1; /* e is cached */
-
- if ( slapi_entry_has_children( e->ep_entry ) )
- {
- ldap_result_code= LDAP_NOT_ALLOWED_ON_NONLEAF;
- /* retval is -1 */
- goto error_return;
- }
-
- /* Don't call pre-op for Tombstone entries */
- if (!delete_tombstone_entry)
- {
- int rc = 0;
- /*
- * Some present state information is passed through the PBlock to the
- * backend pre-op plugin. To ensure a consistent snapshot of this state
- * we wrap the reading of the entry with the dblock.
- */
- ldap_result_code= get_copy_of_entry(pb, addr, &txn,
- SLAPI_DELETE_EXISTING_ENTRY, !is_replicated_operation);
- free_delete_existing_entry = 1;
- if(ldap_result_code==LDAP_OPERATIONS_ERROR ||
- ldap_result_code==LDAP_INVALID_DN_SYNTAX)
- {
- /* restore original entry so the front-end delete code can free it */
- /* 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);
- 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 flag could be set in a preop plugin (e.g., USN) */
- delete_tombstone_entry = operation_is_flag_set(operation,
- OP_FLAG_TOMBSTONE_ENTRY);
- }
-
- /*
- * Sanity check to avoid to delete a non-tombstone or to tombstone again
- * a tombstone entry. This should not happen (see bug 561003).
- */
- is_tombstone_entry = slapi_entry_flag_is_set(e->ep_entry, SLAPI_ENTRY_FLAG_TOMBSTONE);
- if (delete_tombstone_entry) {
- PR_ASSERT(is_tombstone_entry);
- if (!is_tombstone_entry) {
- slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete",
- "Attempt to delete a non-tombstone entry %s\n", dn);
- delete_tombstone_entry = 0;
- }
- } else {
- PR_ASSERT(!is_tombstone_entry);
- if (is_tombstone_entry) {
- slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete",
- "Attempt to Tombstone again a tombstone entry %s\n", dn);
- delete_tombstone_entry = 1;
- }
- }
-
- /*
- * If a CSN is set, we need to tombstone the entry,
- * rather than deleting it outright.
- */
- opcsn = operation_get_csn (operation);
- if (!delete_tombstone_entry)
- {
- if ((opcsn == NULL) && !is_fixup_operation && operation->o_csngen_handler)
- {
- /*
- * Current op is a user request. Opcsn will be assigned
- * by entry_assign_operation_csn() if the dn is in an
- * updatable replica.
- */
- opcsn = entry_assign_operation_csn ( pb, e->ep_entry, NULL );
- }
- if (opcsn != NULL)
- {
- if (!is_fixup_operation)
- {
- entry_set_maxcsn (e->ep_entry, opcsn);
- }
- }
- /*
- * We are dealing with replication and if we haven't been called to
- * remove a tombstone, then it's because we want to create a new one.
- */
- if ( slapi_operation_get_replica_attr (pb, operation, "nsds5ReplicaTombstonePurgeInterval",
- &create_tombstone_entry) == 0 )
- {
- create_tombstone_entry = (create_tombstone_entry < 0) ? 0 : 1;
- }
- }
-
-#if DEBUG
- slapi_log_error(SLAPI_LOG_REPL, "ldbm_back_delete",
- "entry: %s - flags: delete %d is_tombstone_entry %d create %d \n",
- dn, delete_tombstone_entry, is_tombstone_entry, create_tombstone_entry);
-#endif
-
- /* Save away a copy of the entry, before modifications */
- slapi_pblock_set( pb, SLAPI_ENTRY_PRE_OP, slapi_entry_dup( e->ep_entry ));
-
- /* JCMACL - Shouldn't the access check be before the has children check...
- * otherwise we're revealing the fact that an entry exists and has children */
- ldap_result_code = plugin_call_acl_plugin (pb, e->ep_entry, NULL, NULL, SLAPI_ACL_DELETE,
- ACLPLUGIN_ACCESS_DEFAULT, &errbuf );
- if ( ldap_result_code != LDAP_SUCCESS )
- {
- ldap_result_message= errbuf;
- /* retval is -1 */
- goto error_return;
- }
-
- /*
- * Get the entry's parent. We do this here because index_read
- * seems to deadlock the database when dblayer_txn_begin is
- * called.
- */
- slapi_sdn_init(&parentsdn);
- slapi_sdn_get_backend_parent_ext(sdnp, &parentsdn, pb->pb_backend, is_tombstone_entry);
- if ( !slapi_sdn_isempty(&parentsdn) )
- {
- struct backentry *parent = NULL;
- entry_address parent_addr;
-
- parent_addr.sdn = &parentsdn;
- parent_addr.uniqueid = NULL;
- parent = find_entry2modify_only_ext(pb, be, &parent_addr,
- TOMBSTONE_INCLUDED, &txn);
- if (NULL != parent) {
- int isglue;
- size_t haschildren = 0;
- int op = PARENTUPDATE_DEL;
-
- /* Unfortunately findentry doesn't tell us whether it just
- * didn't find the entry, or if there was an error, so we
- * have to assume that the parent wasn't found */
- parent_found = 1;
-
- /* Modify the parent in memory */
- modify_init(&parent_modify_c,parent);
- if (create_tombstone_entry) {
- op |= PARENTUPDATE_CREATE_TOMBSTONE;
- } else if (delete_tombstone_entry) {
- op |= PARENTUPDATE_DELETE_TOMBSTONE;
- }
- retval = parent_update_on_childchange(&parent_modify_c,
- op, &haschildren);
- /* The modify context now contains info needed later */
- if (0 != retval) {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
-
- /*
- * Replication urp_post_delete will delete the parent entry
- * if it is a glue entry without any more children.
- * Those urp condition checkings are done here to
- * save unnecessary entry dup.
- */
- isglue = slapi_entry_attr_hasvalue (parent_modify_c.new_entry->ep_entry,
- SLAPI_ATTR_OBJECTCLASS, "glue");
- if ( opcsn && parent_modify_c.new_entry && !haschildren && isglue)
- {
- slapi_pblock_set ( pb, SLAPI_DELETE_GLUE_PARENT_ENTRY,
- slapi_entry_dup (parent_modify_c.new_entry->ep_entry) );
- }
- }
- }
- slapi_sdn_done(&parentsdn);
-
- if(create_tombstone_entry)
- {
- /*
- * The entry is not removed from the disk when we tombstone an
- * entry. We change the DN, add objectclass=tombstone, and record
- * the UniqueID of the parent entry.
- */
- const char *childuniqueid= slapi_entry_get_uniqueid(e->ep_entry);
- const char *parentuniqueid= NULL;
- char *tombstone_dn = compute_entry_tombstone_dn(slapi_entry_get_dn(e->ep_entry),
- childuniqueid);
- Slapi_Value *tomb_value;
-
- slapi_sdn_set_ndn_byval(&nscpEntrySDN, slapi_sdn_get_ndn(slapi_entry_get_sdn(e->ep_entry)));
-
- /* Copy the entry unique_id for URP conflict checking */
- e_uniqueid = slapi_ch_strdup(childuniqueid);
-
- if(parent_modify_c.old_entry!=NULL)
- {
- /* The suffix entry has no parent */
- parentuniqueid= slapi_entry_get_uniqueid(parent_modify_c.old_entry->ep_entry);
- }
- tombstone = backentry_dup( e );
- slapi_entry_set_dn(tombstone->ep_entry,tombstone_dn); /* Consumes DN */
- if (entryrdn_get_switch()) /* subtree-rename: on */
- {
- Slapi_RDN *srdn = slapi_entry_get_srdn(tombstone->ep_entry);
- char *tombstone_rdn =
- compute_entry_tombstone_rdn(slapi_entry_get_rdn_const(e->ep_entry),
- childuniqueid);
- /* e_srdn has "uniaqueid=..., <ORIG RDN>" */
- slapi_rdn_replace_rdn(srdn, tombstone_rdn);
- slapi_ch_free_string(&tombstone_rdn);
- }
- /* Set tombstone flag on ep_entry */
- slapi_entry_set_flag(tombstone->ep_entry, SLAPI_ENTRY_FLAG_TOMBSTONE);
-
- if(parentuniqueid!=NULL)
- {
- /* The suffix entry has no parent */
- slapi_entry_add_string(tombstone->ep_entry, SLAPI_ATTR_VALUE_PARENT_UNIQUEID, parentuniqueid);
- }
- slapi_entry_add_string(tombstone->ep_entry, SLAPI_ATTR_NSCP_ENTRYDN, slapi_sdn_get_ndn(&nscpEntrySDN));
- tomb_value = slapi_value_new_string(SLAPI_ATTR_VALUE_TOMBSTONE);
- value_update_csn(tomb_value, CSN_TYPE_VALUE_UPDATED,
- operation_get_csn(operation));
- slapi_entry_add_value(tombstone->ep_entry, SLAPI_ATTR_OBJECTCLASS, tomb_value);
- slapi_value_free(&tomb_value);
- /* XXXggood above used to be: slapi_entry_add_string(tombstone->ep_entry, SLAPI_ATTR_OBJECTCLASS, SLAPI_ATTR_VALUE_TOMBSTONE); */
- /* JCMREPL - Add a description of what's going on? */
-
- if ( (original_tombstone = backentry_dup( tombstone )) == NULL ) {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
- }
-
- if (!is_ruv && !is_fixup_operation && !delete_tombstone_entry) {
- ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
- if (-1 == ruv_c_init) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm_back_delete: ldbm_txn_ruv_modify_context "
- "failed to construct RUV modify context\n",
- 0, 0, 0);
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- retval = 0;
- goto error_return;
- }
- }
-
/*
* So, we believe that no code up till here actually added anything
* to the persistent store. From now on, we're transacted
*/
-
txn.back_txn_txn = NULL; /* ready to create the child transaction */
for (retry_count = 0; retry_count < RETRY_TIMES; retry_count++) {
if (txn.back_txn_txn && (txn.back_txn_txn != parent_txn)) {
Slapi_Entry *ent = NULL;
- dblayer_txn_abort(li,&txn);
+ /* Don't release SERIAL LOCK */
+ dblayer_txn_abort_ext(li, &txn, PR_FALSE);
slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
/* reset original entry */
@@ -498,7 +237,13 @@ ldbm_back_delete( Slapi_PBlock *pb )
}
#endif
}
- retval = dblayer_txn_begin(li,parent_txn,&txn);
+ if (0 == retry_count) {
+ /* First time, hold SERIAL LOCK */
+ retval = dblayer_txn_begin(be, parent_txn, &txn);
+ } else {
+ /* Otherwise, no SERIAL LOCK */
+ retval = dblayer_txn_begin_ext(li, parent_txn, &txn, PR_FALSE);
+ }
if (0 != retval) {
if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
ldap_result_code= LDAP_OPERATIONS_ERROR;
@@ -508,29 +253,323 @@ 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 */
- /* these should not need to modify the entry to be deleted -
- if for some reason they ever do, do not use e->ep_entry since
- it could be in the cache and referenced by other search threads -
- instead, have them modify a copy of the entry */
- retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN);
- if (retval) {
- LDAPDebug1Arg( LDAP_DEBUG_TRACE,
- "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);
+ if (0 == retry_count) { /* just once */
+ /* find and lock the entry we are about to modify */
+ if ( (e = find_entry2modify( pb, be, addr, &txn )) == NULL )
+ {
+ ldap_result_code= LDAP_NO_SUCH_OBJECT;
+ retval = -1;
+ goto error_return; /* error result sent by find_entry2modify() */
}
- if (!opreturn) {
- slapi_pblock_get( pb, SLAPI_PLUGIN_OPRETURN, &opreturn );
+ e_in_cache = 1; /* e is cached */
+
+ if ( slapi_entry_has_children( e->ep_entry ) )
+ {
+ ldap_result_code= LDAP_NOT_ALLOWED_ON_NONLEAF;
+ retval = -1;
+ goto error_return;
}
- if (!opreturn) {
- slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN,
- ldap_result_code ?
- &ldap_result_code : &retval );
+
+ /* Don't call pre-op for Tombstone entries */
+ if (!delete_tombstone_entry)
+ {
+ int rc = 0;
+ /*
+ * Some present state information is passed through the PBlock to the
+ * backend pre-op plugin. To ensure a consistent snapshot of this state
+ * we wrap the reading of the entry with the dblock.
+ */
+ ldap_result_code= get_copy_of_entry(pb, addr, &txn,
+ SLAPI_DELETE_EXISTING_ENTRY, !is_replicated_operation);
+ free_delete_existing_entry = 1;
+ if(ldap_result_code==LDAP_OPERATIONS_ERROR ||
+ ldap_result_code==LDAP_INVALID_DN_SYNTAX)
+ {
+ /* restore original entry so the front-end delete code can free it */
+ retval = -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);
+ 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 = -1;
+ goto error_return;
+ }
+ /* the flag could be set in a preop plugin (e.g., USN) */
+ delete_tombstone_entry = operation_is_flag_set(operation,
+ OP_FLAG_TOMBSTONE_ENTRY);
+ }
+
+ /* call the transaction pre delete plugins just after the
+ * to-be-deleted entry is prepared. */
+ /* these should not need to modify the entry to be deleted -
+ if for some reason they ever do, do not use e->ep_entry since
+ it could be in the cache and referenced by other search threads -
+ instead, have them modify a copy of the entry */
+ retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN);
+ if (retval) {
+ LDAPDebug1Arg( LDAP_DEBUG_TRACE,
+ "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);
+ }
+ if (!opreturn) {
+ slapi_pblock_get( pb, SLAPI_PLUGIN_OPRETURN, &opreturn );
+ }
+ if (!opreturn) {
+ slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN,
+ ldap_result_code ?
+ &ldap_result_code : &retval );
+ }
+ goto error_return;
+ }
+
+ /*
+ * Sanity check to avoid to delete a non-tombstone or to tombstone again
+ * a tombstone entry. This should not happen (see bug 561003).
+ */
+ is_tombstone_entry = slapi_entry_flag_is_set(e->ep_entry, SLAPI_ENTRY_FLAG_TOMBSTONE);
+ if (delete_tombstone_entry) {
+ PR_ASSERT(is_tombstone_entry);
+ if (!is_tombstone_entry) {
+ slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete",
+ "Attempt to delete a non-tombstone entry %s\n", dn);
+ delete_tombstone_entry = 0;
+ }
+ } else {
+ PR_ASSERT(!is_tombstone_entry);
+ if (is_tombstone_entry) {
+ slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete",
+ "Attempt to Tombstone again a tombstone entry %s\n", dn);
+ delete_tombstone_entry = 1;
+ }
+ }
+
+ /*
+ * If a CSN is set, we need to tombstone the entry,
+ * rather than deleting it outright.
+ */
+ opcsn = operation_get_csn (operation);
+ if (!delete_tombstone_entry)
+ {
+ if ((opcsn == NULL) && !is_fixup_operation && operation->o_csngen_handler)
+ {
+ /*
+ * Current op is a user request. Opcsn will be assigned
+ * by entry_assign_operation_csn() if the dn is in an
+ * updatable replica.
+ */
+ opcsn = entry_assign_operation_csn ( pb, e->ep_entry, NULL );
+ }
+ if (opcsn != NULL)
+ {
+ if (!is_fixup_operation)
+ {
+ entry_set_maxcsn (e->ep_entry, opcsn);
+ }
+ }
+ /*
+ * We are dealing with replication and if we haven't been called to
+ * remove a tombstone, then it's because we want to create a new one.
+ */
+ if ( slapi_operation_get_replica_attr (pb, operation, "nsds5ReplicaTombstonePurgeInterval",
+ &create_tombstone_entry) == 0 )
+ {
+ create_tombstone_entry = (create_tombstone_entry < 0) ? 0 : 1;
+ }
+ }
+
+#ifdef DEBUG
+ slapi_log_error(SLAPI_LOG_REPL, "ldbm_back_delete",
+ "entry: %s - flags: delete %d is_tombstone_entry %d create %d \n",
+ dn, delete_tombstone_entry, is_tombstone_entry, create_tombstone_entry);
+#endif
+
+ /* Save away a copy of the entry, before modifications */
+ slapi_pblock_set( pb, SLAPI_ENTRY_PRE_OP, slapi_entry_dup( e->ep_entry ));
+
+ /* JCMACL - Shouldn't the access check be before the has children check...
+ * otherwise we're revealing the fact that an entry exists and has children */
+ ldap_result_code = plugin_call_acl_plugin (pb, e->ep_entry, NULL, NULL, SLAPI_ACL_DELETE,
+ ACLPLUGIN_ACCESS_DEFAULT, &errbuf );
+ if ( ldap_result_code != LDAP_SUCCESS )
+ {
+ ldap_result_message= errbuf;
+ retval = -1;
+ goto error_return;
+ }
+
+ /*
+ * Get the entry's parent. We do this here because index_read
+ * seems to deadlock the database when dblayer_txn_begin is
+ * called.
+ */
+ slapi_sdn_init(&parentsdn);
+ slapi_sdn_get_backend_parent_ext(sdnp, &parentsdn, pb->pb_backend, is_tombstone_entry);
+ if ( !slapi_sdn_isempty(&parentsdn) )
+ {
+ struct backentry *parent = NULL;
+ entry_address parent_addr;
+
+ parent_addr.sdn = &parentsdn;
+ parent_addr.uniqueid = NULL;
+ parent = find_entry2modify_only_ext(pb, be, &parent_addr,
+ TOMBSTONE_INCLUDED, &txn);
+ if (NULL != parent) {
+ int isglue;
+ size_t haschildren = 0;
+ int op = PARENTUPDATE_DEL;
+
+ /* Unfortunately findentry doesn't tell us whether it just
+ * didn't find the entry, or if there was an error, so we
+ * have to assume that the parent wasn't found */
+ parent_found = 1;
+
+ /* Modify the parent in memory */
+ modify_init(&parent_modify_c,parent);
+ if (create_tombstone_entry) {
+ op |= PARENTUPDATE_CREATE_TOMBSTONE;
+ } else if (delete_tombstone_entry) {
+ op |= PARENTUPDATE_DELETE_TOMBSTONE;
+ }
+ retval = parent_update_on_childchange(&parent_modify_c,
+ op, &haschildren);
+ /* The modify context now contains info needed later */
+ if (0 != retval) {
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ retval = -1;
+ goto error_return;
+ }
+
+ /*
+ * Replication urp_post_delete will delete the parent entry
+ * if it is a glue entry without any more children.
+ * Those urp condition checkings are done here to
+ * save unnecessary entry dup.
+ */
+ isglue = slapi_entry_attr_hasvalue (parent_modify_c.new_entry->ep_entry,
+ SLAPI_ATTR_OBJECTCLASS, "glue");
+ if ( opcsn && parent_modify_c.new_entry && !haschildren && isglue)
+ {
+ slapi_pblock_set ( pb, SLAPI_DELETE_GLUE_PARENT_ENTRY,
+ slapi_entry_dup (parent_modify_c.new_entry->ep_entry) );
+ }
+ }
+ }
+ slapi_sdn_done(&parentsdn);
+
+ if(create_tombstone_entry)
+ {
+ /*
+ * The entry is not removed from the disk when we tombstone an
+ * entry. We change the DN, add objectclass=tombstone, and record
+ * the UniqueID of the parent entry.
+ */
+ const char *childuniqueid= slapi_entry_get_uniqueid(e->ep_entry);
+ const char *parentuniqueid= NULL;
+ char *tombstone_dn = compute_entry_tombstone_dn(slapi_entry_get_dn(e->ep_entry),
+ childuniqueid);
+ Slapi_Value *tomb_value;
+
+ slapi_sdn_set_ndn_byval(&nscpEntrySDN, slapi_sdn_get_ndn(slapi_entry_get_sdn(e->ep_entry)));
+
+ /* Copy the entry unique_id for URP conflict checking */
+ e_uniqueid = slapi_ch_strdup(childuniqueid);
+
+ if(parent_modify_c.old_entry!=NULL)
+ {
+ /* The suffix entry has no parent */
+ parentuniqueid= slapi_entry_get_uniqueid(parent_modify_c.old_entry->ep_entry);
+ }
+ tombstone = backentry_dup( e );
+ slapi_entry_set_dn(tombstone->ep_entry,tombstone_dn); /* Consumes DN */
+ if (entryrdn_get_switch()) /* subtree-rename: on */
+ {
+ Slapi_RDN *srdn = slapi_entry_get_srdn(tombstone->ep_entry);
+ char *tombstone_rdn =
+ compute_entry_tombstone_rdn(slapi_entry_get_rdn_const(e->ep_entry),
+ childuniqueid);
+ /* e_srdn has "uniaqueid=..., <ORIG RDN>" */
+ slapi_rdn_replace_rdn(srdn, tombstone_rdn);
+ slapi_ch_free_string(&tombstone_rdn);
+ }
+ /* Set tombstone flag on ep_entry */
+ slapi_entry_set_flag(tombstone->ep_entry, SLAPI_ENTRY_FLAG_TOMBSTONE);
+
+ if(parentuniqueid!=NULL)
+ {
+ /* The suffix entry has no parent */
+ slapi_entry_add_string(tombstone->ep_entry, SLAPI_ATTR_VALUE_PARENT_UNIQUEID, parentuniqueid);
+ }
+ slapi_entry_add_string(tombstone->ep_entry, SLAPI_ATTR_NSCP_ENTRYDN, slapi_sdn_get_ndn(&nscpEntrySDN));
+ tomb_value = slapi_value_new_string(SLAPI_ATTR_VALUE_TOMBSTONE);
+ value_update_csn(tomb_value, CSN_TYPE_VALUE_UPDATED,
+ operation_get_csn(operation));
+ slapi_entry_add_value(tombstone->ep_entry, SLAPI_ATTR_OBJECTCLASS, tomb_value);
+ slapi_value_free(&tomb_value);
+ /* XXXggood above used to be: slapi_entry_add_string(tombstone->ep_entry, SLAPI_ATTR_OBJECTCLASS, SLAPI_ATTR_VALUE_TOMBSTONE); */
+ /* JCMREPL - Add a description of what's going on? */
+
+ if ( (original_tombstone = backentry_dup( tombstone )) == NULL ) {
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ retval = -1;
+ goto error_return;
+ }
+ }
+
+ if (!is_ruv && !is_fixup_operation && !delete_tombstone_entry) {
+ ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
+ if (-1 == ruv_c_init) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ldbm_back_delete: ldbm_txn_ruv_modify_context "
+ "failed to construct RUV modify context\n",
+ 0, 0, 0);
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ retval = 0;
+ goto error_return;
+ }
+ }
+ } /* if (0 == retry_count) just once */
+ else {
+ /* call the transaction pre delete plugins not just once
+ * but every time transaction is restarted. */
+ /* these should not need to modify the entry to be deleted -
+ if for some reason they ever do, do not use e->ep_entry since
+ it could be in the cache and referenced by other search threads -
+ instead, have them modify a copy of the entry */
+ retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN);
+ if (retval) {
+ LDAPDebug1Arg( LDAP_DEBUG_TRACE,
+ "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);
+ }
+ if (!opreturn) {
+ slapi_pblock_get( pb, SLAPI_PLUGIN_OPRETURN, &opreturn );
+ }
+ if (!opreturn) {
+ slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN,
+ ldap_result_code ?
+ &ldap_result_code : &retval );
+ }
+ goto error_return;
}
- goto error_return;
}
if(create_tombstone_entry)
@@ -1021,7 +1060,8 @@ ldbm_back_delete( Slapi_PBlock *pb )
goto error_return;
}
- retval = dblayer_txn_commit(li,&txn);
+ /* Release SERIAL LOCK */
+ retval = dblayer_txn_commit(be, &txn);
/* after commit - txn is no longer valid - replace SLAPI_TXN with parent */
slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
if (0 != retval)
@@ -1103,7 +1143,7 @@ error_return:
slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN, &retval );
}
- /* call the transaction post delete plugins just before the commit */
+ /* call the transaction post delete plugins just before the abort */
if (plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN)) {
LDAPDebug1Arg( LDAP_DEBUG_ANY, "SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN plugin "
"returned error code %d\n", retval );
@@ -1118,7 +1158,8 @@ error_return:
}
}
- dblayer_txn_abort(li,&txn); /* abort crashes in case disk full */
+ /* Release SERIAL LOCK */
+ dblayer_txn_abort(be, &txn); /* abort crashes in case disk full */
/* txn is no longer valid - reset the txn pointer to the parent */
slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
}
@@ -1169,10 +1210,6 @@ diskfull_return:
slapi_send_ldap_result( pb, ldap_result_code, NULL, ldap_result_message, 0, NULL );
}
modify_term(&parent_modify_c,be);
- if(dblock_acquired)
- {
- dblayer_unlock_backend(be);
- }
if (rc == 0 && opcsn && !is_fixup_operation && !delete_tombstone_entry)
{
/* URP Naming Collision
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
index 6d2e6f6..1eaaaae 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
@@ -327,7 +327,6 @@ ldbm_back_modify( Slapi_PBlock *pb )
char *ldap_result_message= NULL;
int rc = 0;
Slapi_Operation *operation;
- int dblock_acquired= 0;
entry_address *addr;
int ec_in_cache = 0;
int is_fixup_operation= 0;
@@ -388,113 +387,22 @@ ldbm_back_modify( Slapi_PBlock *pb )
* But, this lock is re-enterant for the fixup
* operations that the URP code in the Replication
* plugin generates.
- */
+ *
+ * SERIALLOCK is moved to dblayer_txn_begin along with exposing be
+ * transaction to plugins (see slapi_back_transaction_* APIs).
+ *
if(SERIALLOCK(li) && !operation_is_flag_set(operation,OP_FLAG_REPL_FIXUP)) {
dblayer_lock_backend(be);
dblock_acquired= 1;
}
-
- /* find and lock the entry we are about to modify */
- if ( (e = find_entry2modify( pb, be, addr, &txn )) == NULL ) {
- ldap_result_code= -1;
- goto error_return; /* error result sent by find_entry2modify() */
- }
-
- if ( !is_fixup_operation )
- {
- opcsn = operation_get_csn (operation);
- if (NULL == opcsn && operation->o_csngen_handler)
- {
- /*
- * Current op is a user request. Opcsn will be assigned
- * if the dn is in an updatable replica.
- */
- opcsn = entry_assign_operation_csn ( pb, e->ep_entry, NULL );
- }
- if (opcsn)
- {
- entry_set_maxcsn (e->ep_entry, opcsn);
- }
- }
-
- /* Save away a copy of the entry, before modifications */
- slapi_pblock_set( pb, SLAPI_ENTRY_PRE_OP, slapi_entry_dup( e->ep_entry ));
-
- if ( (ldap_result_code = plugin_call_acl_mods_access( pb, e->ep_entry, mods, &errbuf)) != LDAP_SUCCESS ) {
- ldap_result_message= errbuf;
- goto error_return;
- }
-
- /* create a copy of the entry and apply the changes to it */
- if ( (ec = backentry_dup( e )) == NULL ) {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
-
- if(!repl_op){
- remove_illegal_mods(mods);
- }
-
- /* ec is the entry that our bepreop should get to mess with */
- slapi_pblock_set( pb, SLAPI_MODIFY_EXISTING_ENTRY, ec->ep_entry );
- slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
-
- if ((opreturn = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_MODIFY_FN)) ||
- (slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code) && ldap_result_code) ||
- (slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &opreturn) && opreturn)) {
- slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
- slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &opreturn);
- if (!ldap_result_code) {
- LDAPDebug0Args(LDAP_DEBUG_ANY, "ldbm_back_modify: SLAPI_PLUGIN_BE_PRE_MODIFY_FN "
- "returned error but did not set SLAPI_RESULT_CODE\n");
- ldap_result_code = LDAP_OPERATIONS_ERROR;
- }
- if (!opreturn) {
- opreturn = -1;
- slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, &opreturn);
- }
- }
- /* The Plugin may have messed about with some of the PBlock parameters... ie. mods */
- slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );
- slapi_mods_init_byref(&smods,mods);
- mod_count = slapi_mods_get_num_mods(&smods);
-
- /* apply the mods, check for syntax, schema problems, etc. */
- if (modify_apply_check_expand(pb, operation, mods, e, ec, &postentry,
- &ldap_result_code, &ldap_result_message)) {
- goto error_return;
- }
-
- if (!is_ruv && !is_fixup_operation) {
- ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
- if (-1 == ruv_c_init) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm_back_modify: ldbm_txn_ruv_modify_context "
- "failed to construct RUV modify context\n",
- 0, 0, 0);
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- retval = 0;
- goto error_return;
- }
- }
-
- /*
- * Grab a copy of the mods and the entry in case the be_txn_preop changes
- * the them. If we have a failure, then we need to reset the mods to their
- * their original state;
*/
- mods_original = copy_mods(mods);
- if ( (original_entry = backentry_dup( ec )) == NULL ) {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
-
txn.back_txn_txn = NULL; /* ready to create the child transaction */
for (retry_count = 0; retry_count < RETRY_TIMES; retry_count++) {
int cache_rc = 0;
int new_mod_count = 0;
if (txn.back_txn_txn && (txn.back_txn_txn != parent_txn)) {
- dblayer_txn_abort(li,&txn);
+ /* don't release SERIAL LOCK */
+ dblayer_txn_abort_ext(li, &txn, PR_FALSE);
slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
/*
* Since be_txn_preop functions could have modified the entry/mods,
@@ -527,17 +435,120 @@ ldbm_back_modify( Slapi_PBlock *pb )
}
/* Nothing above here modifies persistent store, everything after here is subject to the transaction */
- retval = dblayer_txn_begin(li,parent_txn,&txn);
-
+ /* dblayer_txn_begin holds SERIAL lock,
+ * which should be outside of locking the entry (find_entry2modify) */
+ if (0 == retry_count) {
+ /* First time, hold SERIAL LOCK */
+ retval = dblayer_txn_begin(be, parent_txn, &txn);
+ } else {
+ /* Otherwise, no SERIAL LOCK */
+ retval = dblayer_txn_begin_ext(li, parent_txn, &txn, PR_FALSE);
+ }
if (0 != retval) {
if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
}
-
/* stash the transaction for plugins */
slapi_pblock_set(pb, SLAPI_TXN, txn.back_txn_txn);
+ if (0 == retry_count) { /* just once */
+ /* find and lock the entry we are about to modify */
+ if ( (e = find_entry2modify( pb, be, addr, &txn )) == NULL ) {
+ ldap_result_code= -1;
+ goto error_return; /* error result sent by find_entry2modify() */
+ }
+
+ if ( !is_fixup_operation )
+ {
+ opcsn = operation_get_csn (operation);
+ if (NULL == opcsn && operation->o_csngen_handler)
+ {
+ /*
+ * Current op is a user request. Opcsn will be assigned
+ * if the dn is in an updatable replica.
+ */
+ opcsn = entry_assign_operation_csn ( pb, e->ep_entry, NULL );
+ }
+ if (opcsn)
+ {
+ entry_set_maxcsn (e->ep_entry, opcsn);
+ }
+ }
+
+ /* Save away a copy of the entry, before modifications */
+ slapi_pblock_set( pb, SLAPI_ENTRY_PRE_OP, slapi_entry_dup( e->ep_entry ));
+
+ if ( (ldap_result_code = plugin_call_acl_mods_access( pb, e->ep_entry, mods, &errbuf)) != LDAP_SUCCESS ) {
+ ldap_result_message= errbuf;
+ goto error_return;
+ }
+
+ /* create a copy of the entry and apply the changes to it */
+ if ( (ec = backentry_dup( e )) == NULL ) {
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ goto error_return;
+ }
+
+ if(!repl_op){
+ remove_illegal_mods(mods);
+ }
+
+ /* ec is the entry that our bepreop should get to mess with */
+ slapi_pblock_set( pb, SLAPI_MODIFY_EXISTING_ENTRY, ec->ep_entry );
+ slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
+
+ if ((opreturn = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_MODIFY_FN)) ||
+ (slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code) && ldap_result_code) ||
+ (slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &opreturn) && opreturn)) {
+ slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
+ slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &opreturn);
+ if (!ldap_result_code) {
+ LDAPDebug0Args(LDAP_DEBUG_ANY, "ldbm_back_modify: SLAPI_PLUGIN_BE_PRE_MODIFY_FN "
+ "returned error but did not set SLAPI_RESULT_CODE\n");
+ ldap_result_code = LDAP_OPERATIONS_ERROR;
+ }
+ if (!opreturn) {
+ opreturn = -1;
+ slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, &opreturn);
+ }
+ }
+ /* The Plugin may have messed about with some of the PBlock parameters... ie. mods */
+ slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );
+ slapi_mods_init_byref(&smods,mods);
+ mod_count = slapi_mods_get_num_mods(&smods);
+
+ /* apply the mods, check for syntax, schema problems, etc. */
+ if (modify_apply_check_expand(pb, operation, mods, e, ec, &postentry,
+ &ldap_result_code, &ldap_result_message)) {
+ goto error_return;
+ }
+
+ if (!is_ruv && !is_fixup_operation) {
+ ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
+ if (-1 == ruv_c_init) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ldbm_back_modify: ldbm_txn_ruv_modify_context "
+ "failed to construct RUV modify context\n",
+ 0, 0, 0);
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ retval = 0;
+ goto error_return;
+ }
+ }
+
+ /*
+ * Grab a copy of the mods and the entry in case the be_txn_preop changes
+ * the them. If we have a failure, then we need to reset the mods to their
+ * their original state;
+ */
+ mods_original = copy_mods(mods);
+ if ( (original_entry = backentry_dup( ec )) == NULL ) {
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ goto error_return;
+ }
+ } /* if (0 == retry_count) just once */
+
/* call the transaction pre modify plugins just after creating the transaction */
if ((retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN))) {
LDAPDebug1Arg( LDAP_DEBUG_TRACE, "SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN plugin "
@@ -707,7 +718,8 @@ ldbm_back_modify( Slapi_PBlock *pb )
goto error_return;
}
- retval = dblayer_txn_commit(li,&txn);
+ /* Release SERIAL LOCK */
+ retval = dblayer_txn_commit(be, &txn);
/* after commit - txn is no longer valid - replace SLAPI_TXN with parent */
slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
if (0 != retval) {
@@ -766,7 +778,8 @@ error_return:
}
/* It is safer not to abort when the transaction is not started. */
- dblayer_txn_abort(li,&txn); /* abort crashes in case disk full */
+ /* Release SERIAL LOCK */
+ dblayer_txn_abort(be, &txn); /* abort crashes in case disk full */
/* txn is no longer valid - reset the txn pointer to the parent */
slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
}
@@ -812,10 +825,6 @@ common_return:
modify_term(&ruv_c, be);
}
- if(dblock_acquired)
- {
- dblayer_unlock_backend(be);
- }
if(ldap_result_code!=-1)
{
slapi_send_ldap_result( pb, ldap_result_code, NULL, ldap_result_message, 0, NULL );
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
index c7d821a..00e0d61 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
@@ -108,7 +108,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
Slapi_Mods smods_generated = {0};
Slapi_Mods smods_generated_wsi = {0};
Slapi_Operation *operation;
- int dblock_acquired= 0;
int is_replicated_operation= 0;
int is_fixup_operation = 0;
entry_address new_addr;
@@ -204,7 +203,10 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
* the backend has committed the change and released
* the dblock. Acquire the dblock again for them
* if OP_FLAG_ACTION_INVOKE_FOR_REPLOP is set.
- */
+ *
+ * SERIALLOCK is moved to dblayer_txn_begin along with exposing be
+ * transaction to plugins (see slapi_back_transaction_* APIs).
+ *
if(SERIALLOCK(li) &&
(!operation_is_flag_set(operation,OP_FLAG_REPL_FIXUP) ||
operation_is_flag_set(operation,OP_FLAG_ACTION_INVOKE_FOR_REPLOP)))
@@ -212,536 +214,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
dblayer_lock_backend(be);
dblock_acquired= 1;
}
-
- rc = 0;
- rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY);
- rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_PARENT_ENTRY);
- rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_NEWPARENT_ENTRY);
- rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_TARGET_ENTRY);
- while(rc!=0)
- {
- /* JCM - copying entries can be expensive... should optimize */
- /*
- * Some present state information is passed through the PBlock to the
- * backend pre-op plugin. To ensure a consistent snapshot of this state
- * we wrap the reading of the entry with the dblock.
- */
- /* <new rdn>,<new superior> */
- if(slapi_isbitset_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY))
- {
- /* see if an entry with the new name already exists */
- done_with_pblock_entry(pb,SLAPI_MODRDN_EXISTING_ENTRY); /* Could be through this multiple times */
- /* newrdn is normalized, bu tno need to be case-ignored as
- * it's passed to slapi_sdn_init_normdn_byref */
- slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn);
- slapi_sdn_init_normdn_byref(&dn_newrdn, newrdn);
- newdn= moddn_get_newdn(pb,sdn, &dn_newrdn, dn_newsuperiordn);
- slapi_sdn_set_dn_passin(&dn_newdn,newdn);
- new_addr.sdn = &dn_newdn;
- new_addr.udn = NULL;
- /* check dn syntax on newdn */
- ldap_result_code = slapi_dn_syntax_check(pb,
- (char *)slapi_sdn_get_ndn(&dn_newdn), 1);
- if (ldap_result_code)
- {
- ldap_result_code = LDAP_INVALID_DN_SYNTAX;
- slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
- goto error_return;
- }
- new_addr.uniqueid = NULL;
- ldap_result_code= get_copy_of_entry(pb, &new_addr, &txn, SLAPI_MODRDN_EXISTING_ENTRY, 0);
- if(ldap_result_code==LDAP_OPERATIONS_ERROR ||
- ldap_result_code==LDAP_INVALID_DN_SYNTAX)
- {
- goto error_return;
- }
- free_modrdn_existing_entry = 1; /* need to free it */
- }
-
- /* <old superior> */
- if(slapi_isbitset_int(rc,SLAPI_RTN_BIT_FETCH_PARENT_ENTRY))
- {
- /* find and lock the old parent entry */
- done_with_pblock_entry(pb,SLAPI_MODRDN_PARENT_ENTRY); /* Could be through this multiple times */
- oldparent_addr.sdn = &dn_parentdn;
- oldparent_addr.uniqueid = NULL;
- ldap_result_code= get_copy_of_entry(pb, &oldparent_addr, &txn, SLAPI_MODRDN_PARENT_ENTRY, !is_replicated_operation);
- }
-
- /* <new superior> */
- if(slapi_sdn_get_ndn(dn_newsuperiordn)!=NULL &&
- slapi_isbitset_int(rc,SLAPI_RTN_BIT_FETCH_NEWPARENT_ENTRY))
- {
- /* find and lock the new parent entry */
- done_with_pblock_entry(pb,SLAPI_MODRDN_NEWPARENT_ENTRY); /* Could be through this multiple times */
- /* Check that this really is a new superior,
- * and not the same old one. Compare parentdn & newsuperior */
- if (slapi_sdn_compare(dn_newsuperiordn, &dn_parentdn) == 0)
- {
- slapi_sdn_done(dn_newsuperiordn);
- }
- else
- {
- entry_address my_addr;
- if (is_replicated_operation)
- {
- /* If this is a replicated operation,
- * then should fetch new superior with uniqueid */
- slapi_pblock_get (pb, SLAPI_MODRDN_NEWSUPERIOR_ADDRESS,
- &newsuperior_addr);
- }
- else
- {
- my_addr.sdn = dn_newsuperiordn;
- my_addr.uniqueid = NULL;
- newsuperior_addr = &my_addr;
- }
- ldap_result_code= get_copy_of_entry(pb, newsuperior_addr, &txn, SLAPI_MODRDN_NEWPARENT_ENTRY, !is_replicated_operation);
- }
- }
-
- /* <old rdn>,<old superior> */
- if(slapi_isbitset_int(rc,SLAPI_RTN_BIT_FETCH_TARGET_ENTRY))
- {
- /* find and lock the entry we are about to modify */
- done_with_pblock_entry(pb,SLAPI_MODRDN_TARGET_ENTRY); /* Could be through this multiple times */
- slapi_pblock_get (pb, SLAPI_TARGET_ADDRESS, &old_addr);
- ldap_result_code= get_copy_of_entry(pb, old_addr, &txn, SLAPI_MODRDN_TARGET_ENTRY, !is_replicated_operation);
- if(ldap_result_code==LDAP_OPERATIONS_ERROR ||
- ldap_result_code==LDAP_INVALID_DN_SYNTAX)
- {
- /* JCM - Usually the call to find_entry2modify would generate the result code. */
- /* JCM !!! */
- goto error_return;
- }
- }
- /* Call the Backend Pre ModRDN plugins */
- slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
- rc= plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_MODRDN_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);
- }
- if (!opreturn) {
- slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &opreturn);
- }
- if (!opreturn) {
- slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &rc );
- }
- goto error_return;
- }
- /*
- * (rc!=-1) means that the plugin changed things, so we go around
- * the loop once again to get the new present state.
- */
- /* JCMREPL - Warning: A Plugin could cause an infinite loop by always returning a result code that requires some action. */
- }
-
- /* find and lock the entry we are about to modify */
- /* JCMREPL - Argh, what happens about the stinking referrals? */
- slapi_pblock_get (pb, SLAPI_TARGET_ADDRESS, &old_addr);
- e = find_entry2modify( pb, be, old_addr, &txn );
- if ( e == NULL )
- {
- ldap_result_code= -1;
- goto error_return; /* error result sent by find_entry2modify() */
- }
- e_in_cache = 1; /* e is in the cache and locked */
- /* Check that an entry with the same DN doesn't already exist. */
- {
- Slapi_Entry *entry;
- slapi_pblock_get( pb, SLAPI_MODRDN_EXISTING_ENTRY, &entry);
- if((entry != NULL) &&
- /* allow modrdn even if the src dn and dest dn are identical */
- (0 != slapi_sdn_compare((const Slapi_DN *)&dn_newdn,
- (const Slapi_DN *)sdn)))
- {
- ldap_result_code= LDAP_ALREADY_EXISTS;
- goto error_return;
- }
- }
-
- /* Fetch and lock the parent of the entry that is moving */
- oldparent_addr.sdn = &dn_parentdn;
- oldparent_addr.uniqueid = NULL;
- parententry = find_entry2modify_only( pb, be, &oldparent_addr, &txn );
- modify_init(&parent_modify_context,parententry);
-
- /* Fetch and lock the new parent of the entry that is moving */
- if(slapi_sdn_get_ndn(dn_newsuperiordn) != NULL)
- {
- slapi_pblock_get (pb, SLAPI_MODRDN_NEWSUPERIOR_ADDRESS, &newsuperior_addr);
- newparententry = find_entry2modify_only( pb, be, newsuperior_addr, &txn );
- modify_init(&newparent_modify_context,newparententry);
- }
-
- opcsn = operation_get_csn (operation);
- if (!is_fixup_operation)
- {
- if ( opcsn == NULL && operation->o_csngen_handler)
- {
- /*
- * Current op is a user request. Opcsn will be assigned
- * if the dn is in an updatable replica.
- */
- opcsn = entry_assign_operation_csn ( pb, e->ep_entry, parententry ? parententry->ep_entry : NULL );
- }
- if ( opcsn != NULL )
- {
- entry_set_maxcsn (e->ep_entry, opcsn);
- }
- }
-
- /*
- * Now that we have the old entry, we reset the old DN and recompute
- * the new DN. Why? Because earlier when we computed the new DN, we did
- * not have the old entry, so we used the DN that was presented as the
- * target DN in the ModRDN operation itself, and we would prefer to
- * preserve the case and spacing that are in the actual entry's DN
- * instead. Otherwise, a ModRDN operation will potentially change an
- * entry's entire DN (at least with respect to case and spacing).
- */
- slapi_sdn_copy( slapi_entry_get_sdn_const( e->ep_entry ), sdn );
- slapi_pblock_set( pb, SLAPI_MODRDN_TARGET_SDN, sdn );
- if (newparententry != NULL) {
- /* don't forget we also want to preserve case of new superior */
- if (NULL == dn_newsuperiordn) {
- dn_newsuperiordn = slapi_sdn_dup(
- slapi_entry_get_sdn_const(newparententry->ep_entry));
- } else {
- slapi_sdn_copy(slapi_entry_get_sdn_const(newparententry->ep_entry),
- dn_newsuperiordn);
- }
- slapi_pblock_set( pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, dn_newsuperiordn );
- }
- slapi_sdn_set_dn_passin(&dn_newdn,
- moddn_get_newdn(pb, sdn, &dn_newrdn, dn_newsuperiordn));
-
- /* Check that we're allowed to add an entry below the new superior */
- if ( newparententry == NULL )
- {
- /* There may not be a new parent because we don't intend there to be one. */
- if(slapi_sdn_get_ndn(dn_newsuperiordn)!=NULL)
- {
- /* If the new entry is to be a suffix, and we're root, then it's OK that the new parent doesn't exist */
- if (!(slapi_be_issuffix(pb->pb_backend, &dn_newdn)) && isroot)
- {
- /* Here means that we didn't find the parent */
- int err = 0;
- Slapi_DN ancestorsdn;
- struct backentry *ancestorentry;
- slapi_sdn_init(&ancestorsdn);
- ancestorentry= dn2ancestor(be,&dn_newdn,&ancestorsdn,&txn,&err);
- CACHE_RETURN( &inst->inst_cache, &ancestorentry );
- ldap_result_matcheddn= slapi_ch_strdup((char *) slapi_sdn_get_dn(&ancestorsdn));
- ldap_result_code= LDAP_NO_SUCH_OBJECT;
- LDAPDebug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: New superior "
- "does not exist matched %s, newsuperior = %s\n",
- ldap_result_matcheddn == NULL ? "NULL" :
- ldap_result_matcheddn,
- slapi_sdn_get_ndn(dn_newsuperiordn), 0 );
- slapi_sdn_done(&ancestorsdn);
- goto error_return;
- }
- }
- }
- else
- {
- ldap_result_code= plugin_call_acl_plugin (pb, newparententry->ep_entry, NULL, NULL, SLAPI_ACL_ADD, ACLPLUGIN_ACCESS_DEFAULT, &errbuf );
- if ( ldap_result_code != LDAP_SUCCESS )
- {
- ldap_result_message= errbuf;
- LDAPDebug( LDAP_DEBUG_TRACE, "No access to new superior.\n", 0, 0, 0 );
- goto error_return;
- }
- }
-
- /* Check that the target entry has a parent */
- if ( parententry == NULL )
- {
- /* If the entry a suffix, and we're root, then it's OK that the parent doesn't exist */
- if (!(slapi_be_issuffix(pb->pb_backend, sdn)) && isroot)
- {
- /* Here means that we didn't find the parent */
- ldap_result_matcheddn = "NULL";
- ldap_result_code= LDAP_NO_SUCH_OBJECT;
- LDAPDebug( LDAP_DEBUG_TRACE, "Parent does not exist matched %s, parentdn = %s\n",
- ldap_result_matcheddn, slapi_sdn_get_ndn(&dn_parentdn), 0 );
- goto error_return;
- }
- }
-
- /* If it is a replicated Operation or "subtree-rename" is on,
- * it's allowed to rename entries with children */
- if ( !is_replicated_operation && !entryrdn_get_switch() &&
- slapi_entry_has_children( e->ep_entry ))
- {
- ldap_result_code = LDAP_NOT_ALLOWED_ON_NONLEAF;
- goto error_return;
- }
-
- /*
- * JCM - All the child entries must be locked in the cache, so the size of
- * subtree that can be renamed is limited by the cache size.
- */
-
- /* Save away a copy of the entry, before modifications */
- slapi_pblock_set( pb, SLAPI_ENTRY_PRE_OP, slapi_entry_dup( e->ep_entry ));
-
- /* create a copy of the entry and apply the changes to it */
- if ( (ec = backentry_dup( e )) == NULL )
- {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
-
- /* JCMACL - Should be performed before the child check. */
- /* JCMACL - Why is the check performed against the copy, rather than the existing entry? */
- ldap_result_code = plugin_call_acl_plugin (pb, ec->ep_entry,
- NULL /*attr*/, NULL /*value*/, SLAPI_ACL_WRITE,
- ACLPLUGIN_ACCESS_MODRDN, &errbuf );
- if ( ldap_result_code != LDAP_SUCCESS )
- {
- goto error_return;
- }
-
- /* Set the new dn to the copy of the entry */
- slapi_entry_set_sdn( ec->ep_entry, &dn_newdn );
- if (entryrdn_get_switch()) { /* subtree-rename: on */
- Slapi_RDN srdn;
- /* Set the new rdn to the copy of the entry; store full dn in e_srdn */
- slapi_rdn_init_all_sdn(&srdn, &dn_newdn);
- slapi_entry_set_srdn(ec->ep_entry, &srdn);
- slapi_rdn_done(&srdn);
- }
-
- /* create it in the cache - prevents others from creating it */
- if (( cache_add_tentative( &inst->inst_cache, ec, NULL ) != 0 ) ) {
- ec_in_cache = 0; /* not in cache */
- /* allow modrdn even if the src dn and dest dn are identical */
- if ( 0 != slapi_sdn_compare((const Slapi_DN *)&dn_newdn,
- (const Slapi_DN *)sdn) ) {
- /* somebody must've created it between dn2entry() and here */
- /* JCMREPL - Hmm... we can't permit this to happen...? */
- ldap_result_code= LDAP_ALREADY_EXISTS;
- goto error_return;
- }
- /* so if the old dn is the same as the new dn, the entry will not be cached
- until it is replaced with cache_replace */
- } else {
- ec_in_cache = 1;
- }
-
- /* Build the list of modifications required to the existing entry */
- {
- slapi_mods_init(&smods_generated,4);
- slapi_mods_init(&smods_generated_wsi,4);
- ldap_result_code = moddn_newrdn_mods(pb, slapi_sdn_get_ndn(sdn),
- ec, &smods_generated_wsi, is_replicated_operation);
- if (ldap_result_code != LDAP_SUCCESS) {
- if (ldap_result_code == LDAP_UNWILLING_TO_PERFORM)
- ldap_result_message = "Modification of old rdn attribute type not allowed.";
- goto error_return;
- }
- if (!entryrdn_get_switch()) /* subtree-rename: off */
- {
- /*
- * Remove the old entrydn index entry, and add the new one.
- */
- slapi_mods_add( &smods_generated, LDAP_MOD_DELETE, LDBM_ENTRYDN_STR,
- strlen(backentry_get_ndn(e)), backentry_get_ndn(e));
- slapi_mods_add( &smods_generated, LDAP_MOD_REPLACE, LDBM_ENTRYDN_STR,
- strlen(backentry_get_ndn(ec)), backentry_get_ndn(ec));
- }
-
- /*
- * Update parentid if we have a new superior.
- */
- if(slapi_sdn_get_dn(dn_newsuperiordn)!=NULL) {
- char buf[40]; /* Enough for an ID */
-
- if (parententry != NULL) {
- sprintf( buf, "%lu", (u_long)parententry->ep_id );
- slapi_mods_add_string(&smods_generated, LDAP_MOD_DELETE, LDBM_PARENTID_STR, buf);
- }
- if (newparententry != NULL) {
- sprintf( buf, "%lu", (u_long)newparententry->ep_id );
- slapi_mods_add_string(&smods_generated, LDAP_MOD_REPLACE, LDBM_PARENTID_STR, buf);
- }
- }
- }
-
- slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );
- slapi_mods_init_byref(&smods_operation_wsi,mods);
-
- /*
- * We are about to pass the last abandon test, so from now on we are
- * committed to finish this operation. Set status to "will complete"
- * before we make our last abandon check to avoid race conditions in
- * the code that processes abandon operations.
- */
- if (operation) {
- operation->o_status = SLAPI_OP_STATUS_WILL_COMPLETE;
- }
- if ( slapi_op_abandoned( pb ) ) {
- goto error_return;
- }
-
- /*
- * First, we apply the generated mods that do not involve any state information.
- */
- if ( entry_apply_mods( ec->ep_entry, slapi_mods_get_ldapmods_byref(&smods_generated) ) != 0 )
- {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- LDAPDebug( LDAP_DEBUG_TRACE, "ldbm_modrdn: entry_apply_mods failed for entry %s\n",
- slapi_entry_get_dn_const(ec->ep_entry), 0, 0);
- goto error_return;
- }
-
- /*
- * Now we apply the generated mods that do involve state information.
- */
- if (slapi_mods_get_num_mods(&smods_generated_wsi)>0)
- {
- if (entry_apply_mods_wsi(ec->ep_entry, &smods_generated_wsi, operation_get_csn(operation), is_replicated_operation)!=0)
- {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- LDAPDebug( LDAP_DEBUG_TRACE, "ldbm_modrdn: entry_apply_mods_wsi failed for entry %s\n",
- slapi_entry_get_dn_const(ec->ep_entry), 0, 0);
- goto error_return;
- }
- }
-
- /*
- * Now we apply the operation mods that do involve state information.
- * (Operational attributes).
- * The following block looks redundent to the one above. But it may
- * be necessary - check the comment for version 1.3.16.22.2.76 of
- * this file and compare that version with its previous one.
*/
- if (slapi_mods_get_num_mods(&smods_operation_wsi)>0)
- {
- if (entry_apply_mods_wsi(ec->ep_entry, &smods_operation_wsi, operation_get_csn(operation), is_replicated_operation)!=0)
- {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- LDAPDebug( LDAP_DEBUG_TRACE, "ldbm_modrdn: entry_apply_mods_wsi (operational attributes) failed for entry %s\n",
- slapi_entry_get_dn_const(ec->ep_entry), 0, 0);
- goto error_return;
- }
- }
- /* check that the entry still obeys the schema */
- if ( slapi_entry_schema_check( pb, ec->ep_entry ) != 0 ) {
- ldap_result_code = LDAP_OBJECT_CLASS_VIOLATION;
- slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
- goto error_return;
- }
-
- /* Check attribute syntax if any new values are being added for the new RDN */
- if (slapi_mods_get_num_mods(&smods_operation_wsi)>0)
- {
- if (slapi_mods_syntax_check(pb, smods_generated_wsi.mods, 0) != 0)
- {
- ldap_result_code = LDAP_INVALID_SYNTAX;
- slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
- goto error_return;
- }
- }
-
- /*
- * Update the DN CSN of the entry.
- */
- entry_add_dncsn(ec->ep_entry,operation_get_csn(operation));
- entry_add_rdn_csn(ec->ep_entry,operation_get_csn(operation));
-
- /*
- * If the entry has a new superior then the subordinate count
- * of the parents must be updated.
- */
- if(slapi_sdn_get_dn(dn_newsuperiordn)!=NULL)
- {
- /*
- * Update the subordinate count of the parents to reflect the moved child.
- */
- if ( parententry!=NULL )
- {
- retval = parent_update_on_childchange(&parent_modify_context,
- PARENTUPDATE_DEL, NULL);
- /* The parent modify context now contains info needed later */
- if (0 != retval)
- {
- goto error_return;
- }
- }
- if ( newparententry!=NULL )
- {
- retval = parent_update_on_childchange(&newparent_modify_context,
- PARENTUPDATE_ADD, NULL);
- /* The newparent modify context now contains info needed later */
- if (0 != retval)
- {
- goto error_return;
- }
- }
- }
-
- /*
- * If the entry has children then we're going to have to rename them all.
- */
- if (slapi_entry_has_children( e->ep_entry ))
- {
- /* JCM - This is where the subtree lock will appear */
- if (entryrdn_get_switch()) /* subtree-rename: on */
- {
- children = moddn_get_children(&txn, pb, be, e, sdn,
- &child_entries, &child_dns);
- }
- else
- {
- children = moddn_get_children(&txn, pb, be, e, sdn,
- &child_entries, NULL);
- }
-
- /* JCM - Shouldn't we perform an access control check on all the children. */
- /* JCMREPL - But, the replication client has total rights over its subtree, so no access check needed. */
- /* JCM - A subtree move could break ACIs, static groups, and dynamic groups. */
- }
-
- if (!is_ruv && !is_fixup_operation) {
- ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
- if (-1 == ruv_c_init) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm_back_modrdn: ldbm_txn_ruv_modify_context "
- "failed to construct RUV modify context\n",
- 0, 0, 0);
- ldap_result_code = LDAP_OPERATIONS_ERROR;
- retval = 0;
- goto error_return;
- }
- }
-
- /*
- * make copies of the originals, no need to copy the mods because
- * we have already copied them
- */
- if ( (original_entry = backentry_dup( ec )) == NULL ) {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
- slapi_pblock_get(pb, SLAPI_MODRDN_TARGET_ENTRY, &target_entry);
- if ( (original_targetentry = slapi_entry_dup(target_entry)) == NULL ) {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
-
- slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn);
- original_newrdn = slapi_ch_strdup(newrdn);
- slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &dn_newsuperiordn);
- orig_dn_newsuperiordn = slapi_sdn_dup(dn_newsuperiordn);
/*
* So, we believe that no code up till here actually added anything
@@ -754,7 +227,8 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
{
Slapi_Entry *ent = NULL;
- dblayer_txn_abort(li,&txn);
+ /* don't release SERIAL LOCK */
+ dblayer_txn_abort_ext(li, &txn, PR_FALSE);
/* txn is no longer valid - reset slapi_txn to the parent */
slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
@@ -836,7 +310,13 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
}
#endif
}
- retval = dblayer_txn_begin(li,parent_txn,&txn);
+ if (0 == retry_count) {
+ /* First time, hold SERIAL LOCK */
+ retval = dblayer_txn_begin(be, parent_txn, &txn);
+ } else {
+ /* Otherwise, no SERIAL LOCK */
+ retval = dblayer_txn_begin_ext(li, parent_txn, &txn, PR_FALSE);
+ }
if (0 != retval) {
ldap_result_code= LDAP_OPERATIONS_ERROR;
if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
@@ -846,6 +326,538 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
/* stash the transaction */
slapi_pblock_set(pb, SLAPI_TXN, (void *)txn.back_txn_txn);
+ if (0 == retry_count) { /* just once */
+ rc = 0;
+ rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY);
+ rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_PARENT_ENTRY);
+ rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_NEWPARENT_ENTRY);
+ rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_TARGET_ENTRY);
+ while(rc!=0)
+ {
+ /* JCM - copying entries can be expensive... should optimize */
+ /*
+ * Some present state information is passed through the PBlock to the
+ * backend pre-op plugin. To ensure a consistent snapshot of this state
+ * we wrap the reading of the entry with the dblock.
+ */
+ /* <new rdn>,<new superior> */
+ if(slapi_isbitset_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY))
+ {
+ /* see if an entry with the new name already exists */
+ done_with_pblock_entry(pb,SLAPI_MODRDN_EXISTING_ENTRY); /* Could be through this multiple times */
+ /* newrdn is normalized, bu tno need to be case-ignored as
+ * it's passed to slapi_sdn_init_normdn_byref */
+ slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn);
+ slapi_sdn_init_normdn_byref(&dn_newrdn, newrdn);
+ newdn= moddn_get_newdn(pb,sdn, &dn_newrdn, dn_newsuperiordn);
+ slapi_sdn_set_dn_passin(&dn_newdn,newdn);
+ new_addr.sdn = &dn_newdn;
+ new_addr.udn = NULL;
+ /* check dn syntax on newdn */
+ ldap_result_code = slapi_dn_syntax_check(pb,
+ (char *)slapi_sdn_get_ndn(&dn_newdn), 1);
+ if (ldap_result_code)
+ {
+ ldap_result_code = LDAP_INVALID_DN_SYNTAX;
+ slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
+ goto error_return;
+ }
+ new_addr.uniqueid = NULL;
+ ldap_result_code= get_copy_of_entry(pb, &new_addr, &txn, SLAPI_MODRDN_EXISTING_ENTRY, 0);
+ if(ldap_result_code==LDAP_OPERATIONS_ERROR ||
+ ldap_result_code==LDAP_INVALID_DN_SYNTAX)
+ {
+ goto error_return;
+ }
+ free_modrdn_existing_entry = 1; /* need to free it */
+ }
+
+ /* <old superior> */
+ if(slapi_isbitset_int(rc,SLAPI_RTN_BIT_FETCH_PARENT_ENTRY))
+ {
+ /* find and lock the old parent entry */
+ done_with_pblock_entry(pb,SLAPI_MODRDN_PARENT_ENTRY); /* Could be through this multiple times */
+ oldparent_addr.sdn = &dn_parentdn;
+ oldparent_addr.uniqueid = NULL;
+ ldap_result_code= get_copy_of_entry(pb, &oldparent_addr, &txn, SLAPI_MODRDN_PARENT_ENTRY, !is_replicated_operation);
+ }
+
+ /* <new superior> */
+ if(slapi_sdn_get_ndn(dn_newsuperiordn)!=NULL &&
+ slapi_isbitset_int(rc,SLAPI_RTN_BIT_FETCH_NEWPARENT_ENTRY))
+ {
+ /* find and lock the new parent entry */
+ done_with_pblock_entry(pb,SLAPI_MODRDN_NEWPARENT_ENTRY); /* Could be through this multiple times */
+ /* Check that this really is a new superior,
+ * and not the same old one. Compare parentdn & newsuperior */
+ if (slapi_sdn_compare(dn_newsuperiordn, &dn_parentdn) == 0)
+ {
+ slapi_sdn_done(dn_newsuperiordn);
+ }
+ else
+ {
+ entry_address my_addr;
+ if (is_replicated_operation)
+ {
+ /* If this is a replicated operation,
+ * then should fetch new superior with uniqueid */
+ slapi_pblock_get (pb, SLAPI_MODRDN_NEWSUPERIOR_ADDRESS,
+ &newsuperior_addr);
+ }
+ else
+ {
+ my_addr.sdn = dn_newsuperiordn;
+ my_addr.uniqueid = NULL;
+ newsuperior_addr = &my_addr;
+ }
+ ldap_result_code= get_copy_of_entry(pb, newsuperior_addr, &txn, SLAPI_MODRDN_NEWPARENT_ENTRY, !is_replicated_operation);
+ }
+ }
+
+ /* <old rdn>,<old superior> */
+ if(slapi_isbitset_int(rc,SLAPI_RTN_BIT_FETCH_TARGET_ENTRY))
+ {
+ /* find and lock the entry we are about to modify */
+ done_with_pblock_entry(pb,SLAPI_MODRDN_TARGET_ENTRY); /* Could be through this multiple times */
+ slapi_pblock_get (pb, SLAPI_TARGET_ADDRESS, &old_addr);
+ ldap_result_code= get_copy_of_entry(pb, old_addr, &txn, SLAPI_MODRDN_TARGET_ENTRY, !is_replicated_operation);
+ if(ldap_result_code==LDAP_OPERATIONS_ERROR ||
+ ldap_result_code==LDAP_INVALID_DN_SYNTAX)
+ {
+ /* JCM - Usually the call to find_entry2modify would generate the result code. */
+ /* JCM !!! */
+ goto error_return;
+ }
+ }
+ /* Call the Backend Pre ModRDN plugins */
+ slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
+ rc= plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_MODRDN_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);
+ }
+ if (!opreturn) {
+ slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &opreturn);
+ }
+ if (!opreturn) {
+ slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &rc );
+ }
+ goto error_return;
+ }
+ /*
+ * (rc!=-1) means that the plugin changed things, so we go around
+ * the loop once again to get the new present state.
+ */
+ /* JCMREPL - Warning: A Plugin could cause an infinite loop by always returning a result code that requires some action. */
+ }
+
+ /* find and lock the entry we are about to modify */
+ /* JCMREPL - Argh, what happens about the stinking referrals? */
+ slapi_pblock_get (pb, SLAPI_TARGET_ADDRESS, &old_addr);
+ e = find_entry2modify( pb, be, old_addr, &txn );
+ if ( e == NULL )
+ {
+ ldap_result_code= -1;
+ goto error_return; /* error result sent by find_entry2modify() */
+ }
+ e_in_cache = 1; /* e is in the cache and locked */
+ /* Check that an entry with the same DN doesn't already exist. */
+ {
+ Slapi_Entry *entry;
+ slapi_pblock_get( pb, SLAPI_MODRDN_EXISTING_ENTRY, &entry);
+ if((entry != NULL) &&
+ /* allow modrdn even if the src dn and dest dn are identical */
+ (0 != slapi_sdn_compare((const Slapi_DN *)&dn_newdn,
+ (const Slapi_DN *)sdn)))
+ {
+ ldap_result_code= LDAP_ALREADY_EXISTS;
+ goto error_return;
+ }
+ }
+
+ /* Fetch and lock the parent of the entry that is moving */
+ oldparent_addr.sdn = &dn_parentdn;
+ oldparent_addr.uniqueid = NULL;
+ parententry = find_entry2modify_only( pb, be, &oldparent_addr, &txn );
+ modify_init(&parent_modify_context,parententry);
+
+ /* Fetch and lock the new parent of the entry that is moving */
+ if(slapi_sdn_get_ndn(dn_newsuperiordn) != NULL)
+ {
+ slapi_pblock_get (pb, SLAPI_MODRDN_NEWSUPERIOR_ADDRESS, &newsuperior_addr);
+ newparententry = find_entry2modify_only( pb, be, newsuperior_addr, &txn );
+ modify_init(&newparent_modify_context,newparententry);
+ }
+
+ opcsn = operation_get_csn (operation);
+ if (!is_fixup_operation)
+ {
+ if ( opcsn == NULL && operation->o_csngen_handler)
+ {
+ /*
+ * Current op is a user request. Opcsn will be assigned
+ * if the dn is in an updatable replica.
+ */
+ opcsn = entry_assign_operation_csn ( pb, e->ep_entry, parententry ? parententry->ep_entry : NULL );
+ }
+ if ( opcsn != NULL )
+ {
+ entry_set_maxcsn (e->ep_entry, opcsn);
+ }
+ }
+
+ /*
+ * Now that we have the old entry, we reset the old DN and recompute
+ * the new DN. Why? Because earlier when we computed the new DN, we did
+ * not have the old entry, so we used the DN that was presented as the
+ * target DN in the ModRDN operation itself, and we would prefer to
+ * preserve the case and spacing that are in the actual entry's DN
+ * instead. Otherwise, a ModRDN operation will potentially change an
+ * entry's entire DN (at least with respect to case and spacing).
+ */
+ slapi_sdn_copy( slapi_entry_get_sdn_const( e->ep_entry ), sdn );
+ slapi_pblock_set( pb, SLAPI_MODRDN_TARGET_SDN, sdn );
+ if (newparententry != NULL) {
+ /* don't forget we also want to preserve case of new superior */
+ if (NULL == dn_newsuperiordn) {
+ dn_newsuperiordn = slapi_sdn_dup(
+ slapi_entry_get_sdn_const(newparententry->ep_entry));
+ } else {
+ slapi_sdn_copy(slapi_entry_get_sdn_const(newparententry->ep_entry),
+ dn_newsuperiordn);
+ }
+ slapi_pblock_set( pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, dn_newsuperiordn );
+ }
+ slapi_sdn_set_dn_passin(&dn_newdn,
+ moddn_get_newdn(pb, sdn, &dn_newrdn, dn_newsuperiordn));
+
+ /* Check that we're allowed to add an entry below the new superior */
+ if ( newparententry == NULL )
+ {
+ /* There may not be a new parent because we don't intend there to be one. */
+ if(slapi_sdn_get_ndn(dn_newsuperiordn)!=NULL)
+ {
+ /* If the new entry is to be a suffix, and we're root, then it's OK that the new parent doesn't exist */
+ if (!(slapi_be_issuffix(pb->pb_backend, &dn_newdn)) && isroot)
+ {
+ /* Here means that we didn't find the parent */
+ int err = 0;
+ Slapi_DN ancestorsdn;
+ struct backentry *ancestorentry;
+ slapi_sdn_init(&ancestorsdn);
+ ancestorentry= dn2ancestor(be,&dn_newdn,&ancestorsdn,&txn,&err);
+ CACHE_RETURN( &inst->inst_cache, &ancestorentry );
+ ldap_result_matcheddn= slapi_ch_strdup((char *) slapi_sdn_get_dn(&ancestorsdn));
+ ldap_result_code= LDAP_NO_SUCH_OBJECT;
+ LDAPDebug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: New superior "
+ "does not exist matched %s, newsuperior = %s\n",
+ ldap_result_matcheddn == NULL ? "NULL" :
+ ldap_result_matcheddn,
+ slapi_sdn_get_ndn(dn_newsuperiordn), 0 );
+ slapi_sdn_done(&ancestorsdn);
+ goto error_return;
+ }
+ }
+ }
+ else
+ {
+ ldap_result_code= plugin_call_acl_plugin (pb, newparententry->ep_entry, NULL, NULL, SLAPI_ACL_ADD, ACLPLUGIN_ACCESS_DEFAULT, &errbuf );
+ if ( ldap_result_code != LDAP_SUCCESS )
+ {
+ ldap_result_message= errbuf;
+ LDAPDebug( LDAP_DEBUG_TRACE, "No access to new superior.\n", 0, 0, 0 );
+ goto error_return;
+ }
+ }
+
+ /* Check that the target entry has a parent */
+ if ( parententry == NULL )
+ {
+ /* If the entry a suffix, and we're root, then it's OK that the parent doesn't exist */
+ if (!(slapi_be_issuffix(pb->pb_backend, sdn)) && isroot)
+ {
+ /* Here means that we didn't find the parent */
+ ldap_result_matcheddn = "NULL";
+ ldap_result_code= LDAP_NO_SUCH_OBJECT;
+ LDAPDebug( LDAP_DEBUG_TRACE, "Parent does not exist matched %s, parentdn = %s\n",
+ ldap_result_matcheddn, slapi_sdn_get_ndn(&dn_parentdn), 0 );
+ goto error_return;
+ }
+ }
+
+ /* If it is a replicated Operation or "subtree-rename" is on,
+ * it's allowed to rename entries with children */
+ if ( !is_replicated_operation && !entryrdn_get_switch() &&
+ slapi_entry_has_children( e->ep_entry ))
+ {
+ ldap_result_code = LDAP_NOT_ALLOWED_ON_NONLEAF;
+ goto error_return;
+ }
+
+ /*
+ * JCM - All the child entries must be locked in the cache, so the size of
+ * subtree that can be renamed is limited by the cache size.
+ */
+
+ /* Save away a copy of the entry, before modifications */
+ slapi_pblock_set( pb, SLAPI_ENTRY_PRE_OP, slapi_entry_dup( e->ep_entry ));
+
+ /* create a copy of the entry and apply the changes to it */
+ if ( (ec = backentry_dup( e )) == NULL )
+ {
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ goto error_return;
+ }
+
+ /* JCMACL - Should be performed before the child check. */
+ /* JCMACL - Why is the check performed against the copy, rather than the existing entry? */
+ ldap_result_code = plugin_call_acl_plugin (pb, ec->ep_entry,
+ NULL /*attr*/, NULL /*value*/, SLAPI_ACL_WRITE,
+ ACLPLUGIN_ACCESS_MODRDN, &errbuf );
+ if ( ldap_result_code != LDAP_SUCCESS )
+ {
+ goto error_return;
+ }
+
+ /* Set the new dn to the copy of the entry */
+ slapi_entry_set_sdn( ec->ep_entry, &dn_newdn );
+ if (entryrdn_get_switch()) { /* subtree-rename: on */
+ Slapi_RDN srdn;
+ /* Set the new rdn to the copy of the entry; store full dn in e_srdn */
+ slapi_rdn_init_all_sdn(&srdn, &dn_newdn);
+ slapi_entry_set_srdn(ec->ep_entry, &srdn);
+ slapi_rdn_done(&srdn);
+ }
+
+ /* create it in the cache - prevents others from creating it */
+ if (( cache_add_tentative( &inst->inst_cache, ec, NULL ) != 0 ) ) {
+ ec_in_cache = 0; /* not in cache */
+ /* allow modrdn even if the src dn and dest dn are identical */
+ if ( 0 != slapi_sdn_compare((const Slapi_DN *)&dn_newdn,
+ (const Slapi_DN *)sdn) ) {
+ /* somebody must've created it between dn2entry() and here */
+ /* JCMREPL - Hmm... we can't permit this to happen...? */
+ ldap_result_code= LDAP_ALREADY_EXISTS;
+ goto error_return;
+ }
+ /* so if the old dn is the same as the new dn, the entry will not be cached
+ until it is replaced with cache_replace */
+ } else {
+ ec_in_cache = 1;
+ }
+
+ /* Build the list of modifications required to the existing entry */
+ {
+ slapi_mods_init(&smods_generated,4);
+ slapi_mods_init(&smods_generated_wsi,4);
+ ldap_result_code = moddn_newrdn_mods(pb, slapi_sdn_get_ndn(sdn),
+ ec, &smods_generated_wsi, is_replicated_operation);
+ if (ldap_result_code != LDAP_SUCCESS) {
+ if (ldap_result_code == LDAP_UNWILLING_TO_PERFORM)
+ ldap_result_message = "Modification of old rdn attribute type not allowed.";
+ goto error_return;
+ }
+ if (!entryrdn_get_switch()) /* subtree-rename: off */
+ {
+ /*
+ * Remove the old entrydn index entry, and add the new one.
+ */
+ slapi_mods_add( &smods_generated, LDAP_MOD_DELETE, LDBM_ENTRYDN_STR,
+ strlen(backentry_get_ndn(e)), backentry_get_ndn(e));
+ slapi_mods_add( &smods_generated, LDAP_MOD_REPLACE, LDBM_ENTRYDN_STR,
+ strlen(backentry_get_ndn(ec)), backentry_get_ndn(ec));
+ }
+
+ /*
+ * Update parentid if we have a new superior.
+ */
+ if(slapi_sdn_get_dn(dn_newsuperiordn)!=NULL) {
+ char buf[40]; /* Enough for an ID */
+
+ if (parententry != NULL) {
+ sprintf( buf, "%lu", (u_long)parententry->ep_id );
+ slapi_mods_add_string(&smods_generated, LDAP_MOD_DELETE, LDBM_PARENTID_STR, buf);
+ }
+ if (newparententry != NULL) {
+ sprintf( buf, "%lu", (u_long)newparententry->ep_id );
+ slapi_mods_add_string(&smods_generated, LDAP_MOD_REPLACE, LDBM_PARENTID_STR, buf);
+ }
+ }
+ }
+
+ slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );
+ slapi_mods_init_byref(&smods_operation_wsi,mods);
+
+ /*
+ * We are about to pass the last abandon test, so from now on we are
+ * committed to finish this operation. Set status to "will complete"
+ * before we make our last abandon check to avoid race conditions in
+ * the code that processes abandon operations.
+ */
+ if (operation) {
+ operation->o_status = SLAPI_OP_STATUS_WILL_COMPLETE;
+ }
+ if ( slapi_op_abandoned( pb ) ) {
+ goto error_return;
+ }
+
+ /*
+ * First, we apply the generated mods that do not involve any state information.
+ */
+ if ( entry_apply_mods( ec->ep_entry, slapi_mods_get_ldapmods_byref(&smods_generated) ) != 0 )
+ {
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ LDAPDebug( LDAP_DEBUG_TRACE, "ldbm_modrdn: entry_apply_mods failed for entry %s\n",
+ slapi_entry_get_dn_const(ec->ep_entry), 0, 0);
+ goto error_return;
+ }
+
+ /*
+ * Now we apply the generated mods that do involve state information.
+ */
+ if (slapi_mods_get_num_mods(&smods_generated_wsi)>0)
+ {
+ if (entry_apply_mods_wsi(ec->ep_entry, &smods_generated_wsi, operation_get_csn(operation), is_replicated_operation)!=0)
+ {
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ LDAPDebug( LDAP_DEBUG_TRACE, "ldbm_modrdn: entry_apply_mods_wsi failed for entry %s\n",
+ slapi_entry_get_dn_const(ec->ep_entry), 0, 0);
+ goto error_return;
+ }
+ }
+
+ /*
+ * Now we apply the operation mods that do involve state information.
+ * (Operational attributes).
+ * The following block looks redundent to the one above. But it may
+ * be necessary - check the comment for version 1.3.16.22.2.76 of
+ * this file and compare that version with its previous one.
+ */
+ if (slapi_mods_get_num_mods(&smods_operation_wsi)>0)
+ {
+ if (entry_apply_mods_wsi(ec->ep_entry, &smods_operation_wsi, operation_get_csn(operation), is_replicated_operation)!=0)
+ {
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ LDAPDebug( LDAP_DEBUG_TRACE, "ldbm_modrdn: entry_apply_mods_wsi (operational attributes) failed for entry %s\n",
+ slapi_entry_get_dn_const(ec->ep_entry), 0, 0);
+ goto error_return;
+ }
+ }
+ /* check that the entry still obeys the schema */
+ if ( slapi_entry_schema_check( pb, ec->ep_entry ) != 0 ) {
+ ldap_result_code = LDAP_OBJECT_CLASS_VIOLATION;
+ slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
+ goto error_return;
+ }
+
+ /* Check attribute syntax if any new values are being added for the new RDN */
+ if (slapi_mods_get_num_mods(&smods_operation_wsi)>0)
+ {
+ if (slapi_mods_syntax_check(pb, smods_generated_wsi.mods, 0) != 0)
+ {
+ ldap_result_code = LDAP_INVALID_SYNTAX;
+ slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
+ goto error_return;
+ }
+ }
+
+ /*
+ * Update the DN CSN of the entry.
+ */
+ entry_add_dncsn(ec->ep_entry,operation_get_csn(operation));
+ entry_add_rdn_csn(ec->ep_entry,operation_get_csn(operation));
+
+ /*
+ * If the entry has a new superior then the subordinate count
+ * of the parents must be updated.
+ */
+ if(slapi_sdn_get_dn(dn_newsuperiordn)!=NULL)
+ {
+ /*
+ * Update the subordinate count of the parents to reflect the moved child.
+ */
+ if ( parententry!=NULL )
+ {
+ retval = parent_update_on_childchange(&parent_modify_context,
+ PARENTUPDATE_DEL, NULL);
+ /* The parent modify context now contains info needed later */
+ if (0 != retval)
+ {
+ goto error_return;
+ }
+ }
+ if ( newparententry!=NULL )
+ {
+ retval = parent_update_on_childchange(&newparent_modify_context,
+ PARENTUPDATE_ADD, NULL);
+ /* The newparent modify context now contains info needed later */
+ if (0 != retval)
+ {
+ goto error_return;
+ }
+ }
+ }
+
+ /*
+ * If the entry has children then we're going to have to rename them all.
+ */
+ if (slapi_entry_has_children( e->ep_entry ))
+ {
+ /* JCM - This is where the subtree lock will appear */
+ if (entryrdn_get_switch()) /* subtree-rename: on */
+ {
+ children = moddn_get_children(&txn, pb, be, e, sdn,
+ &child_entries, &child_dns);
+ }
+ else
+ {
+ children = moddn_get_children(&txn, pb, be, e, sdn,
+ &child_entries, NULL);
+ }
+
+ /* JCM - Shouldn't we perform an access control check on all the children. */
+ /* JCMREPL - But, the replication client has total rights over its subtree, so no access check needed. */
+ /* JCM - A subtree move could break ACIs, static groups, and dynamic groups. */
+ }
+
+ if (!is_ruv && !is_fixup_operation) {
+ ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
+ if (-1 == ruv_c_init) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ldbm_back_modrdn: ldbm_txn_ruv_modify_context "
+ "failed to construct RUV modify context\n",
+ 0, 0, 0);
+ ldap_result_code = LDAP_OPERATIONS_ERROR;
+ retval = 0;
+ goto error_return;
+ }
+ }
+
+ /*
+ * make copies of the originals, no need to copy the mods because
+ * we have already copied them
+ */
+ if ( (original_entry = backentry_dup( ec )) == NULL ) {
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ goto error_return;
+ }
+ slapi_pblock_get(pb, SLAPI_MODRDN_TARGET_ENTRY, &target_entry);
+ if ( (original_targetentry = slapi_entry_dup(target_entry)) == NULL ) {
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ goto error_return;
+ }
+
+ slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn);
+ original_newrdn = slapi_ch_strdup(newrdn);
+ slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &dn_newsuperiordn);
+ orig_dn_newsuperiordn = slapi_sdn_dup(dn_newsuperiordn);
+ } /* if (0 == retry_count) just once */
+
/* call the transaction pre modrdn plugins just after creating the transaction */
if ((retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_MODRDN_FN))) {
LDAPDebug1Arg( LDAP_DEBUG_TRACE, "SLAPI_PLUGIN_BE_TXN_PRE_MODRDN_FN plugin "
@@ -1089,7 +1101,8 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
goto error_return;
}
- retval = dblayer_txn_commit(li,&txn);
+ /* Release SERIAL LOCK */
+ retval = dblayer_txn_commit(be, &txn);
/* after commit - txn is no longer valid - replace SLAPI_TXN with parent */
slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
if (0 != retval)
@@ -1224,7 +1237,7 @@ error_return:
opreturn = -1;
slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN, &opreturn );
}
- /* call the transaction post modrdn plugins just before the commit */
+ /* call the transaction post modrdn plugins just before the abort */
if ((retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN))) {
LDAPDebug1Arg( LDAP_DEBUG_TRACE, "SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN plugin "
"returned error code %d\n", retval );
@@ -1239,7 +1252,8 @@ error_return:
}
}
- dblayer_txn_abort(li,&txn); /* abort crashes in case disk full */
+ /* Release SERIAL LOCK */
+ dblayer_txn_abort(be, &txn); /* abort crashes in case disk full */
/* txn is no longer valid - reset the txn pointer to the parent */
slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
}
@@ -1317,11 +1331,6 @@ common_return:
backentry_free(&original_parent);
backentry_free(&original_newparent);
slapi_entry_free(original_targetentry);
-
- if(dblock_acquired)
- {
- dblayer_unlock_backend(be);
- }
slapi_ch_free((void**)&errbuf);
if (retval == 0 && opcsn != NULL && !is_fixup_operation)
{
diff --git a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
index f28235f..9c024ca 100644
--- a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
+++ b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
@@ -2174,7 +2174,7 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb)
svals = attr_get_present_values(attr);
if (!run_from_cmdline) {
- rc = dblayer_txn_begin(li, NULL, &txn);
+ rc = dblayer_txn_begin(be, NULL, &txn);
if (0 != rc) {
LDAPDebug(LDAP_DEBUG_ANY,
"%s: ERROR: failed to begin txn for update "
@@ -2211,13 +2211,13 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb)
indexAttrs[j], rc, dblayer_strerror(rc));
}
if (!run_from_cmdline) {
- dblayer_txn_abort(li, &txn);
+ dblayer_txn_abort(be, &txn);
}
return_value = -2;
goto err_out;
}
if (!run_from_cmdline) {
- rc = dblayer_txn_commit(li, &txn);
+ rc = dblayer_txn_commit(be, &txn);
if (0 != rc) {
LDAPDebug(LDAP_DEBUG_ANY,
"%s: ERROR: failed to commit txn for "
@@ -2250,7 +2250,7 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb)
goto err_out;
}
if (!run_from_cmdline) {
- rc = dblayer_txn_begin(li, NULL, &txn);
+ rc = dblayer_txn_begin(be, NULL, &txn);
if (0 != rc) {
LDAPDebug(LDAP_DEBUG_ANY,
"%s: ERROR: failed to begin txn for update index '%s'\n",
@@ -2277,7 +2277,7 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb)
vlv_release_lock(be);
if (!run_from_cmdline)
{
- rc = dblayer_txn_commit(li, &txn);
+ rc = dblayer_txn_commit(be, &txn);
if (0 != rc) {
LDAPDebug(LDAP_DEBUG_ANY,
"%s: ERROR: failed to commit txn for update index '%s'\n",
@@ -2322,7 +2322,7 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb)
if (index_ext & DB2INDEX_ENTRYRDN) {
if (entryrdn_get_switch()) { /* subtree-rename: on */
if (!run_from_cmdline) {
- rc = dblayer_txn_begin(li, NULL, &txn);
+ rc = dblayer_txn_begin(be, NULL, &txn);
if (0 != rc) {
LDAPDebug1Arg(LDAP_DEBUG_ANY,
"%s: ERROR: failed to begin txn for update "
@@ -2355,13 +2355,13 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb)
rc, dblayer_strerror(rc));
}
if (!run_from_cmdline) {
- dblayer_txn_abort(li, &txn);
+ dblayer_txn_abort(be, &txn);
}
return_value = -2;
goto err_out;
}
if (!run_from_cmdline) {
- rc = dblayer_txn_commit(li, &txn);
+ rc = dblayer_txn_commit(be, &txn);
if (0 != rc) {
LDAPDebug1Arg(LDAP_DEBUG_ANY,
"%s: ERROR: failed to commit txn for "
@@ -3314,7 +3314,7 @@ _get_and_add_parent_rdns(backend *be,
if (index_ext & DB2INDEX_ENTRYRDN) {
if (txn && !run_from_cmdline) {
- rc = dblayer_txn_begin(li, NULL, txn);
+ rc = dblayer_txn_begin(be, NULL, txn);
if (rc) {
slapi_log_error(SLAPI_LOG_FATAL, "ldif2dbm",
"%s: ERROR: failed to begin txn for update "
@@ -3335,12 +3335,12 @@ _get_and_add_parent_rdns(backend *be,
"%s: Error %d: %s\n", inst->inst_name, rc,
dblayer_strerror(rc));
if (txn && !run_from_cmdline) {
- dblayer_txn_abort(li, txn);
+ dblayer_txn_abort(be, txn);
}
goto bail;
}
if (txn && !run_from_cmdline) {
- rc = dblayer_txn_commit(li, txn);
+ rc = dblayer_txn_commit(be, txn);
if (rc) {
slapi_log_error(SLAPI_LOG_FATAL, "ldif2dbm",
"%s: ERROR: failed to commit txn for "
diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
index be4120a..80bf329 100644
--- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
+++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
@@ -116,12 +116,18 @@ int dblayer_get_aux_id2entry(backend *be, DB **ppDB, DB_ENV **ppEnv, char **path
int dblayer_get_aux_id2entry_ext(backend *be, DB **ppDB, DB_ENV **ppEnv, char **path, int flags);
int dblayer_release_aux_id2entry(backend *be, DB *pDB, DB_ENV *pEnv);
int dblayer_txn_init(struct ldbminfo *li, back_txn *txn);
-int dblayer_txn_begin(struct ldbminfo *li,back_txnid parent_txn, back_txn *txn);
-int dblayer_txn_commit(struct ldbminfo *li, back_txn *txn);
-int dblayer_txn_abort(struct ldbminfo *li, back_txn *txn);
-int dblayer_read_txn_abort(struct ldbminfo *li, back_txn *txn);
-int dblayer_read_txn_begin(struct ldbminfo *li,back_txnid parent_txn, back_txn *txn);
-int dblayer_read_txn_commit(struct ldbminfo *li, back_txn *txn);
+int dblayer_txn_begin(backend *be,back_txnid parent_txn, back_txn *txn);
+int dblayer_txn_begin_ext(struct ldbminfo *li, back_txnid parent_txn, back_txn *txn, PRBool use_lock);
+int dblayer_txn_commit(backend *be, back_txn *txn);
+int dblayer_txn_commit_ext(struct ldbminfo *li, back_txn *txn, PRBool use_lock);
+int dblayer_txn_abort(backend *be, back_txn *txn);
+int dblayer_txn_abort_ext(struct ldbminfo *li, back_txn *txn, PRBool use_lock);
+int dblayer_read_txn_abort(backend *be, back_txn *txn);
+int dblayer_read_txn_begin(backend *be,back_txnid parent_txn, back_txn *txn);
+int dblayer_read_txn_commit(backend *be, back_txn *txn);
+int dblayer_txn_begin_all(struct ldbminfo *li,back_txnid parent_txn, back_txn *txn);
+int dblayer_txn_commit_all(struct ldbminfo *li, back_txn *txn);
+int dblayer_txn_abort_all(struct ldbminfo *li, back_txn *txn);
size_t dblayer_get_optimal_block_size(struct ldbminfo *li);
void dblayer_unlock_backend(backend *be);
void dblayer_lock_backend(backend *be);
diff --git a/ldap/servers/slapd/backend.c b/ldap/servers/slapd/backend.c
index de852c8..a95c101 100644
--- a/ldap/servers/slapd/backend.c
+++ b/ldap/servers/slapd/backend.c
@@ -620,3 +620,31 @@ slapi_back_ctrl_info(Slapi_Backend *be, int cmd, void *info)
rc = (*be->be_ctrl_info)(be, cmd, info);
return rc;
}
+
+/* API to expose DB transaction begin */
+/* See memberof.c for usage. */
+int
+slapi_back_transaction_begin(Slapi_PBlock *pb)
+{
+ IFP txn_begin;
+ slapi_pblock_get(pb, SLAPI_PLUGIN_DB_BEGIN_FN, (void*)&txn_begin);
+ return txn_begin(pb);
+}
+
+/* API to expose DB transaction commit */
+int
+slapi_back_transaction_commit(Slapi_PBlock *pb)
+{
+ IFP txn_commit;
+ slapi_pblock_get(pb, SLAPI_PLUGIN_DB_COMMIT_FN, (void*)&txn_commit);
+ return txn_commit(pb);
+}
+
+/* API to expose DB transaction abort */
+int
+slapi_back_transaction_abort(Slapi_PBlock *pb)
+{
+ IFP txn_abort;
+ slapi_pblock_get(pb, SLAPI_PLUGIN_DB_ABORT_FN, (void*)&txn_abort);
+ return txn_abort(pb);
+}
diff --git a/ldap/servers/slapd/dse.c b/ldap/servers/slapd/dse.c
index 8cf3916..3d2955c 100644
--- a/ldap/servers/slapd/dse.c
+++ b/ldap/servers/slapd/dse.c
@@ -1967,18 +1967,19 @@ dse_modify(Slapi_PBlock *pb) /* JCM There should only be one exit point from thi
/* next, give the betxn plugins a crack at it */
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &returncode);
slapi_pblock_set(pb, SLAPI_MODIFY_EXISTING_ENTRY, ecc);
- plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN);
- if (!returncode) {
- slapi_pblock_get(pb, SLAPI_RESULT_CODE, &returncode);
- }
- if (returncode && !returntext[0]) {
- char *ldap_result_message = NULL;
- slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
- if (ldap_result_message && ldap_result_message[0]) {
- PL_strncpyz(returntext, ldap_result_message, sizeof(returntext));
- }
- }
if (need_be_postop) {
+ plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN);
+ if (!returncode) {
+ slapi_pblock_get(pb, SLAPI_RESULT_CODE, &returncode);
+ }
+ if (returncode && !returntext[0]) {
+ char *ldap_result_message = NULL;
+ slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
+ if (ldap_result_message && ldap_result_message[0]) {
+ PL_strncpyz(returntext, ldap_result_message, sizeof(returntext));
+ }
+ }
+
plugin_call_plugins(pb, SLAPI_PLUGIN_BE_POST_MODIFY_FN);
if (!returncode) {
slapi_pblock_get(pb, SLAPI_RESULT_CODE, &returncode);
@@ -2198,10 +2199,11 @@ dse_add(Slapi_PBlock *pb) /* JCM There should only be one exit point from this f
returncode = rc;
}
}
- /* next, give the be txn plugins a crack at it */
- slapi_pblock_set(pb, SLAPI_RESULT_CODE, &returncode);
- plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_POST_ADD_FN);
if (need_be_postop) {
+ /* next, give the be txn plugins a crack at it */
+ slapi_pblock_set(pb, SLAPI_RESULT_CODE, &returncode);
+ plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_POST_ADD_FN);
+
/* finally, give the be plugins a crack at it */
plugin_call_plugins(pb, SLAPI_PLUGIN_BE_POST_ADD_FN);
if (!returncode) {
@@ -2287,7 +2289,6 @@ dse_delete(Slapi_PBlock *pb) /* JCM There should only be one exit point from thi
}
if(dse_call_callback(pdse, pb, SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP, ec, NULL, &returncode,returntext)==SLAPI_DSE_CALLBACK_OK) {
- slapi_pblock_get(pb, SLAPI_DELETE_BEPREOP_ENTRY, &orig_entry);
slapi_pblock_set(pb, SLAPI_DELETE_BEPREOP_ENTRY, ec);
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &returncode);
plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_DELETE_FN);
@@ -2306,13 +2307,15 @@ dse_delete(Slapi_PBlock *pb) /* JCM There should only be one exit point from thi
}
}
}
- slapi_pblock_set(pb, SLAPI_DELETE_BEPREOP_ENTRY, orig_entry);
+ /* Setting SLAPI_ENTRY_PRE_OP here,
+ * since some betxn postop may need the pre op entry. */
+ slapi_pblock_set(pb, SLAPI_ENTRY_PRE_OP, slapi_entry_dup(ec));
} else {
goto done;
}
dse_call_callback(pdse, pb, SLAPI_OPERATION_DELETE, DSE_FLAG_POSTOP, ec, NULL, &returncode, returntext);
- done:
+done:
slapi_pblock_get(pb, SLAPI_DELETE_BEPOSTOP_ENTRY, &orig_entry);
slapi_pblock_set(pb, SLAPI_DELETE_BEPOSTOP_ENTRY, ec);
/* make sure OPRETURN and RESULT_CODE are set */
@@ -2325,11 +2328,12 @@ dse_delete(Slapi_PBlock *pb) /* JCM There should only be one exit point from thi
returncode = rc;
}
}
- plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN);
- if (!returncode) {
- slapi_pblock_get(pb, SLAPI_RESULT_CODE, &returncode);
- }
if (need_be_postop) {
+ plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN);
+ if (!returncode) {
+ slapi_pblock_get(pb, SLAPI_RESULT_CODE, &returncode);
+ }
+
/* finally, give the be plugins a crack at it */
plugin_call_plugins(pb, SLAPI_PLUGIN_BE_POST_DELETE_FN);
if (!returncode) {
@@ -2345,9 +2349,6 @@ dse_delete(Slapi_PBlock *pb) /* JCM There should only be one exit point from thi
}
slapi_pblock_set(pb, SLAPI_DELETE_BEPOSTOP_ENTRY, orig_entry);
slapi_send_ldap_result( pb, returncode, NULL, returntext, 0, NULL );
- if (ec) {
- slapi_pblock_set( pb, SLAPI_ENTRY_PRE_OP, slapi_entry_dup( ec ));
- }
return dse_delete_return(returncode, ec);
}
diff --git a/ldap/servers/slapd/entry.c b/ldap/servers/slapd/entry.c
index 1c4569f..85b47a6 100644
--- a/ldap/servers/slapd/entry.c
+++ b/ldap/servers/slapd/entry.c
@@ -2835,27 +2835,31 @@ slapi_entry_attr_get_bool( const Slapi_Entry* e, const char *type)
{
PRBool r = PR_FALSE; /* default if no attr */
Slapi_Attr* attr;
- slapi_entry_attr_find(e, type, &attr);
+ slapi_entry_attr_find(e, type, &attr);
if (attr!=NULL)
{
- Slapi_Value *v;
- const struct berval *bvp;
+ Slapi_Value *v;
+ const struct berval *bvp;
- slapi_valueset_first_value( &attr->a_present_values, &v);
- bvp = slapi_value_get_berval(v);
- if ((bvp == NULL) || (bvp->bv_len == 0)) { /* none or empty == false */
- r = PR_FALSE;
- } else if (!PL_strncasecmp(bvp->bv_val, "true", bvp->bv_len)) {
- r = PR_TRUE;
- } else if (!PL_strncasecmp(bvp->bv_val, "false", bvp->bv_len)) {
- r = PR_FALSE;
- } else if (!PL_strncasecmp(bvp->bv_val, "yes", bvp->bv_len)) {
- r = PR_TRUE;
- } else if (!PL_strncasecmp(bvp->bv_val, "no", bvp->bv_len)) {
- r = PR_FALSE;
- } else { /* assume numeric: 0 - false: non-zero - true */
- r = (PRBool)slapi_value_get_ulong(v);
- }
+ slapi_valueset_first_value( &attr->a_present_values, &v);
+ bvp = slapi_value_get_berval(v);
+ if ((bvp == NULL) || (bvp->bv_len == 0)) { /* none or empty == false */
+ r = PR_FALSE;
+ } else if (!PL_strncasecmp(bvp->bv_val, "on", bvp->bv_len)) {
+ r = PR_TRUE;
+ } else if (!PL_strncasecmp(bvp->bv_val, "off", bvp->bv_len)) {
+ r = PR_FALSE;
+ } else if (!PL_strncasecmp(bvp->bv_val, "true", bvp->bv_len)) {
+ r = PR_TRUE;
+ } else if (!PL_strncasecmp(bvp->bv_val, "false", bvp->bv_len)) {
+ r = PR_FALSE;
+ } else if (!PL_strncasecmp(bvp->bv_val, "yes", bvp->bv_len)) {
+ r = PR_TRUE;
+ } else if (!PL_strncasecmp(bvp->bv_val, "no", bvp->bv_len)) {
+ r = PR_FALSE;
+ } else { /* assume numeric: 0 - false: non-zero - true */
+ r = (PRBool)slapi_value_get_ulong(v);
+ }
}
return r;
}
diff --git a/ldap/servers/slapd/mapping_tree.c b/ldap/servers/slapd/mapping_tree.c
index dad5940..237fc24 100644
--- a/ldap/servers/slapd/mapping_tree.c
+++ b/ldap/servers/slapd/mapping_tree.c
@@ -2643,11 +2643,11 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock *pb,
target_node->mtn_backend_names[*index]);
*be = target_node->mtn_be[*index];
if(*be==NULL) {
- LDAPDebug(LDAP_DEBUG_ANY,
- "Warning: Mapping tree node entry for %s point to "
- "an unknown backend : %s\n",
- slapi_sdn_get_dn(target_node->mtn_subtree),
- target_node->mtn_backend_names[*index], 0);
+ LDAPDebug(LDAP_DEBUG_BACKLDBM,
+ "Warning: Mapping tree node entry for %s "
+ "point to an unknown backend : %s\n",
+ slapi_sdn_get_dn(target_node->mtn_subtree),
+ target_node->mtn_backend_names[*index], 0);
/* Well there's still not backend instance for
* this MTN, so let's have the default backend
* deal with this.
diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c
index 9a5398f..2d4e0b0 100644
--- a/ldap/servers/slapd/pblock.c
+++ b/ldap/servers/slapd/pblock.c
@@ -1966,6 +1966,11 @@ slapi_pblock_set( Slapi_PBlock *pblock, int arg, void *value )
switch ( arg ) {
case SLAPI_BACKEND:
pblock->pb_backend = (Slapi_Backend *) value;
+ if (pblock->pb_backend && (NULL == pblock->pb_plugin)) {
+ /* newly allocated pblock may not have backend plugin set. */
+ pblock->pb_plugin =
+ (struct slapdplugin *)pblock->pb_backend->be_database;
+ }
break;
case SLAPI_BACKEND_COUNT:
pblock->pb_backend_count = *((int *) value);
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 880ad2c..4883ad5 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -5978,6 +5978,40 @@ int slapi_is_root_suffix(Slapi_DN * dn);
const Slapi_DN *slapi_get_suffix_by_dn(const Slapi_DN *dn);
const char * slapi_be_gettype(Slapi_Backend *be);
+/**
+ * Start database transaction
+ *
+ * \param pb Pblock which is supposed to set (Slapi_Backend *) to SLAPI_BACKEND
+ * \return 0 if successful
+ * \return Non-zero if an error occurred
+ *
+ * \see slapi_back_transaction_commit
+ * \see slapi_back_transaction_abort
+ */
+int slapi_back_transaction_begin(Slapi_PBlock *pb);
+/**
+ * Commit database transaction
+ *
+ * \param pb Pblock which is used to start transaction
+ * \return 0 if successful
+ * \return Non-zero if an error occurred
+ *
+ * \see slapi_back_transaction_start
+ * \see slapi_back_transaction_abort
+ */
+int slapi_back_transaction_commit(Slapi_PBlock *pb);
+/**
+ * Abort database transaction
+ *
+ * \param pb Pblock which is used to start transaction
+ * \return 0 if successful
+ * \return Non-zero if an error occurred
+ *
+ * \see slapi_back_transaction_commit
+ * \see slapi_back_transaction_abort
+ */
+int slapi_back_transaction_abort(Slapi_PBlock *pb);
+
int slapi_be_is_flag_set(Slapi_Backend * be, int flag);
void slapi_be_set_flag(Slapi_Backend * be, int flag);
11 years, 6 months
ldap/admin ldap/servers
by Noriko Hosoi
ldap/admin/src/scripts/template-db2index.in | 2
ldap/admin/src/scripts/template-db2index.pl.in | 89 +++++++++----------------
ldap/servers/slapd/back-ldbm/ldif2ldbm.c | 26 +++++--
3 files changed, 55 insertions(+), 62 deletions(-)
New commits:
commit 3c6756f9fa7ddec9d49a3c5492a5902fd1303d7b
Author: Noriko Hosoi <nhosoi(a)totoro.usersys.redhat.com>
Date: Wed Oct 3 14:19:41 2012 -0700
Trac Ticket #453 - db2index with -tattrname:type,type fails
https://fedorahosted.org/389/ticket/453
Fix Description:
1) db2index and db2index.pl did not handle options with no space
between the option type and the value. This patch properly parses
them.
2) db2index_add_indexed_attr now converts the comma delimited list
of index types into multiple values for the nsIndexType and
nsMatchingRule.
diff --git a/ldap/admin/src/scripts/template-db2index.in b/ldap/admin/src/scripts/template-db2index.in
index 3dc4740..ba39c17 100755
--- a/ldap/admin/src/scripts/template-db2index.in
+++ b/ldap/admin/src/scripts/template-db2index.in
@@ -23,7 +23,7 @@ if [ $# -eq 0 ]
then
bak_dir={{BAK-DIR}}/reindex_`date +%Y_%m_%d_%H_%M_%S`
./ns-slapd upgradedb -D {{CONFIG-DIR}} -f -a "$bak_dir"
-elif [ $# -lt 4 ]
+elif [ $# -lt 2 ]
then
echo "Usage: db2index [-n backend_instance | {-s includesuffix}* -t attribute[:indextypes[:matchingrules]] -T vlvattribute]"
exit 1
diff --git a/ldap/admin/src/scripts/template-db2index.pl.in b/ldap/admin/src/scripts/template-db2index.pl.in
index e598b05..46a7ee5 100644
--- a/ldap/admin/src/scripts/template-db2index.pl.in
+++ b/ldap/admin/src/scripts/template-db2index.pl.in
@@ -39,6 +39,13 @@
# END COPYRIGHT BLOCK
#
+use Getopt::Std;
+
+$opt_D = "{{ROOT-DN}}";
+$opt_p = "{{SERVER-PORT}}";
+$opt_h = "{{SERVER-NAME}}";
+$opt_v = 0;
+
sub usage {
print(STDERR "Usage: $0 [-v] -D rootdn { -w password | -w - | -j filename } \n");
print(STDERR " -n instance [-t attributeName[:indextypes[:matchingrules]]]\n");
@@ -56,6 +63,8 @@ sub usage {
print(STDERR " Example: -t foo:eq,pres\n");
print(STDERR " : -T vlvAttributeName - vlvAttributeName: name of the vlv attribute to be indexed\n");
print(STDERR " : -v - verbose\n");
+
+ exit 1;
}
$instance = "";
@@ -77,51 +86,25 @@ libpath_add("/usr/lib");
$ENV{'SHLIB_PATH'} = "$ENV{'LD_LIBRARY_PATH'}";
-$i = 0;
-while ($i <= $#ARGV)
-{
- if ("$ARGV[$i]" eq "-n")
- {
- # instance
- $i++; $instance = $ARGV[$i];
- }
- elsif ("$ARGV[$i]" eq "-D")
- {
- # Directory Manager
- $i++; $rootdn = $ARGV[$i];
- }
- elsif ("$ARGV[$i]" eq "-w")
- {
- # Directory Manager's password
- $i++; $passwd = $ARGV[$i];
- }
- elsif ("$ARGV[$i]" eq "-j")
- {
- # Read Directory Manager's password from a file
- $i++; $passwdfile = $ARGV[$i];
- }
- elsif ("$ARGV[$i]" eq "-t")
- {
- # Attribute to index
- $i++; $attribute_arg = $ARGV[$i];
- }
- elsif ("$ARGV[$i]" eq "-T")
- {
- # Vlvattribute to index
- $i++; $vlvattribute_arg = $ARGV[$i];
- }
- elsif ("$ARGV[$i]" eq "-v")
- {
- # verbose
- $verbose = 1;
- }
- else
- {
- &usage; exit(1);
- }
- $i++;
+usage() if (!getopts('n:D:w:T:t:j:v'));
+
+if ($opt_j ne ""){
+ die "Error, cannot open password file $opt_j\n" unless (open (RPASS, $opt_j));
+ $opt_w = <RPASS>;
+ chomp($opt_w);
+ close(RPASS);
}
+usage() if( $opt_w eq "" );
+usage() if( $#ARGV ge 0 );
+
+$instance = $opt_n;
+$rootdn = $opt_D;
+$passwd = $opt_w;
+$attribute_arg = $opt_t;
+$vlvattribute_arg = $opt_T;
+$verbose = $opt_v;
+
if ($passwdfile ne ""){
# Open file and get the password
unless (open (RPASS, $passwdfile)) {
@@ -132,21 +115,20 @@ if ($passwdfile ne ""){
close(RPASS);
} elsif ($passwd eq "-"){
# Read the password from terminal
- print "Bind Password: ";
- # Disable console echo
- system("@sttyexec@ -echo") if -t STDIN;
- # read the answer
- $passwd = <STDIN>;
- # Enable console echo
- system("@sttyexec@ echo") if -t STDIN;
- print "\n";
- chop($passwd); # trim trailing newline
+ print "Bind Password: ";
+ # Disable console echo
+ system("@sttyexec@ -echo") if -t STDIN;
+ # read the answer
+ $passwd = <STDIN>;
+ # Enable console echo
+ system("@sttyexec@ echo") if -t STDIN;
+ print "\n";
+ chop($passwd); # trim trailing newline
}
if ( $rootdn eq "" || $passwd eq "" )
{
&usage;
- exit(1);
}
$vstr = "";
@@ -162,7 +144,6 @@ $taskname = "db2index_${yr}_${mn}_${dy}_${h}_${m}_${s}";
if ( $instance eq "" )
{
&usage;
- exit(1);
}
# No attribute name has been specified: let's get them from the configuration
diff --git a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
index c802ff2..f28235f 100644
--- a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
+++ b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
@@ -2494,6 +2494,8 @@ db2index_add_indexed_attr(backend *be, char *attrString)
Slapi_Entry *e;
struct berval *vals[2];
struct berval val;
+ char *ptr;
+ char *next;
vals[0] = &val;
vals[1] = NULL;
@@ -2508,6 +2510,7 @@ db2index_add_indexed_attr(backend *be, char *attrString)
/* set the index name */
val.bv_val = attrString+1;
val.bv_len = strlen(attrString);
+ /* bv_val is copied into the entry. */
slapi_entry_add_values(e,"cn",vals);
if (NULL != (mptr = strchr(iptr, ':'))) {
@@ -2516,15 +2519,24 @@ db2index_add_indexed_attr(backend *be, char *attrString)
}
/* set the index type */
- val.bv_val = iptr;
- val.bv_len = strlen(iptr);
- slapi_entry_add_values(e,"nsIndexType",vals);
+ for (ptr = strtok_r(iptr, ", ", &next);
+ ptr;
+ ptr = strtok_r(NULL, ", ", &next)) {
+ val.bv_val = ptr;
+ val.bv_len = strlen(ptr);
+ /* bv_val is copied into the entry. */
+ slapi_entry_add_values(e,"nsIndexType",vals);
+ }
if (NULL != mptr) {
- /* set the matching rule */
- val.bv_val = mptr;
- val.bv_len = strlen(mptr);
- slapi_entry_add_values(e,"nsMatchingRule",vals);
+ for (ptr = strtok_r(mptr, ", ", &next);
+ ptr;
+ ptr = strtok_r(NULL, ", ", &next)) {
+ val.bv_val = ptr;
+ val.bv_len = strlen(ptr);
+ /* bv_val is copied into the entry. */
+ slapi_entry_add_values(e,"nsMatchingRule",vals);
+ }
}
attr_index_config(be, "from db2index()", 0, e, 0, 0);
11 years, 6 months
Branch '389-ds-base-1.2.11' - ldap/schema ldap/servers
by Mark Reynolds
ldap/schema/02common.ldif | 3 ++-
ldap/servers/slapd/pw.c | 5 ++++-
2 files changed, 6 insertions(+), 2 deletions(-)
New commits:
commit 009fd8c21bb8226766fd84e477fae032ab1741c5
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Fri Sep 28 15:00:20 2012 -0400
Ticket 478 - passwordTrackUpdateTime stops working with subtree password policies
Bug Description: If you create a subtree/user password policy passwordTrackUpdateTime
is not checked, bascially turning it off regardless of the setting in
cn=config.
Fix Description: Added a check for passwordTrackUpdateTime in new_passwordPolicy(). Also
added this attribute to the schema so you can manually add it to subtree/user
password policies.
https://fedorahosted.org/389/ticket/478
Reviewed by: Noriko(Thanks!)
(cherry picked from commit 7ba65b0022b9ecb40baaffbcef8130527028ed8b)
diff --git a/ldap/schema/02common.ldif b/ldap/schema/02common.ldif
index c209615..c6cc6b8 100644
--- a/ldap/schema/02common.ldif
+++ b/ldap/schema/02common.ldif
@@ -94,6 +94,7 @@ attributeTypes: ( 2.16.840.1.113730.3.1.2080 NAME ( 'passwordMin8bit' 'pwdMin8bi
attributeTypes: ( 2.16.840.1.113730.3.1.2081 NAME ( 'passwordMaxRepeats' 'pwdMaxRepeats' ) DESC 'Netscape defined password policy 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.2082 NAME ( 'passwordMinCategories' 'pwdMinCategories' ) DESC 'Netscape defined password policy 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.2083 NAME ( 'passwordMinTokenLength' 'pwdMinTokenLength' ) DESC 'Netscape defined password policy 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.2140 NAME ( 'passwordTrackUpdateTime' ) DESC 'Netscape defined password policy 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.198 NAME 'memberURL' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.199 NAME 'memberCertificateDescription' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.207 NAME 'vlvBase' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 X-ORIGIN 'Netscape Directory Server' )
@@ -163,7 +164,7 @@ objectClasses: ( 2.16.840.1.113730.3.2.7 NAME 'nsLicenseUser' DESC 'Netscape def
objectClasses: ( 2.16.840.1.113730.3.2.1 NAME 'changeLogEntry' DESC 'LDAP changelog objectclass' SUP top MUST ( targetdn $ changeTime $ changenumber $ changeType ) MAY ( changes $ newrdn $ deleteoldrdn $ newsuperior ) X-ORIGIN 'Changelog Internet Draft' )
objectClasses: ( 2.16.840.1.113730.3.2.6 NAME 'referral' DESC 'LDAP referrals objectclass' SUP top MAY ( ref ) X-ORIGIN 'LDAPv3 referrals Internet Draft' )
objectClasses: ( 2.16.840.1.113730.3.2.12 NAME 'passwordObject' DESC 'Netscape defined password policy objectclass' SUP top MAY ( pwdpolicysubentry $ passwordExpirationTime $ passwordExpWarned $ passwordRetryCount $ retryCountResetTime $ accountUnlockTime $ passwordHistory $ passwordAllowChangeTime $ passwordGraceUserTime ) X-ORIGIN 'Netscape Directory Server' )
-objectClasses: ( 2.16.840.1.113730.3.2.13 NAME 'passwordPolicy' DESC 'Netscape defined password policy objectclass' SUP top MAY ( passwordMaxAge $ passwordExp $ passwordMinLength $ passwordKeepHistory $ passwordInHistory $ passwordChange $ passwordWarning $ passwordLockout $ passwordMaxFailure $ passwordResetDuration $ passwordUnlock $ passwordLockoutDuration $ passwordCheckSyntax $ passwordMustChange $ passwordStorageScheme $ passwordMinAge $ passwordResetFailureCount $ passwordGraceLimit $ passwordMinDigits $ passwordMinAlphas $ passwordMinUppers $ passwordMinLowers $ passwordMinSpecials $ passwordMin8bit $ passwordMaxRepeats $ passwordMinCategories $ passwordMinTokenLength ) X-ORIGIN 'Netscape Directory Server' )
+objectClasses: ( 2.16.840.1.113730.3.2.13 NAME 'passwordPolicy' DESC 'Netscape defined password policy objectclass' SUP top MAY ( passwordMaxAge $ passwordExp $ passwordMinLength $ passwordKeepHistory $ passwordInHistory $ passwordChange $ passwordWarning $ passwordLockout $ passwordMaxFailure $ passwordResetDuration $ passwordUnlock $ passwordLockoutDuration $ passwordCheckSyntax $ passwordMustChange $ passwordStorageScheme $ passwordMinAge $ passwordResetFailureCount $ passwordGraceLimit $ passwordMinDigits $ passwordMinAlphas $ passwordMinUppers $ passwordMinLowers $ passwordMinSpecials $ passwordMin8bit $ passwordMaxRepeats $ passwordMinCategories $ passwordMinTokenLength $ passwordTrackUpdateTime ) X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.30 NAME 'glue' DESC 'Netscape defined objectclass' SUP top X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.32 NAME 'netscapeMachineData' DESC 'Netscape defined objectclass' SUP top X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.38 NAME 'vlvSearch' DESC 'Netscape defined objectclass' SUP top MUST ( cn $ vlvBase $ vlvScope $ vlvFilter ) MAY ( multiLineDescription ) X-ORIGIN 'Netscape Directory Server' )
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
index 93fc899..6f3d436 100644
--- a/ldap/servers/slapd/pw.c
+++ b/ldap/servers/slapd/pw.c
@@ -1625,10 +1625,13 @@ new_passwdPolicy(Slapi_PBlock *pb, const char *dn)
"--local policy entry not found\n", dn);
goto done;
}
-
+
/* set the default passwordLegacyPolicy setting */
pwdpolicy->pw_is_legacy = 1;
+ /* set passwordTrackUpdateTime */
+ pwdpolicy->pw_track_update_time = slapdFrontendConfig->pw_policy.pw_track_update_time;
+
for (slapi_entry_first_attr(pw_entry, &attr); attr;
slapi_entry_next_attr(pw_entry, attr, &attr))
{
11 years, 6 months
ldap/schema ldap/servers
by Mark Reynolds
ldap/schema/02common.ldif | 3 ++-
ldap/servers/slapd/pw.c | 5 ++++-
2 files changed, 6 insertions(+), 2 deletions(-)
New commits:
commit 7ba65b0022b9ecb40baaffbcef8130527028ed8b
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Fri Sep 28 15:00:20 2012 -0400
Ticket 478 - passwordTrackUpdateTime stops working with subtree password policies
Bug Description: If you create a subtree/user password policy passwordTrackUpdateTime
is not checked, bascially turning it off regardless of the setting in
cn=config.
Fix Description: Added a check for passwordTrackUpdateTime in new_passwordPolicy(). Also
added this attribute to the schema so you can manually add it to subtree/user
password policies.
https://fedorahosted.org/389/ticket/478
Reviewed by: Noriko(Thanks!)
diff --git a/ldap/schema/02common.ldif b/ldap/schema/02common.ldif
index c209615..c6cc6b8 100644
--- a/ldap/schema/02common.ldif
+++ b/ldap/schema/02common.ldif
@@ -94,6 +94,7 @@ attributeTypes: ( 2.16.840.1.113730.3.1.2080 NAME ( 'passwordMin8bit' 'pwdMin8bi
attributeTypes: ( 2.16.840.1.113730.3.1.2081 NAME ( 'passwordMaxRepeats' 'pwdMaxRepeats' ) DESC 'Netscape defined password policy 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.2082 NAME ( 'passwordMinCategories' 'pwdMinCategories' ) DESC 'Netscape defined password policy 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.2083 NAME ( 'passwordMinTokenLength' 'pwdMinTokenLength' ) DESC 'Netscape defined password policy 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.2140 NAME ( 'passwordTrackUpdateTime' ) DESC 'Netscape defined password policy 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.198 NAME 'memberURL' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.199 NAME 'memberCertificateDescription' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.207 NAME 'vlvBase' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 X-ORIGIN 'Netscape Directory Server' )
@@ -163,7 +164,7 @@ objectClasses: ( 2.16.840.1.113730.3.2.7 NAME 'nsLicenseUser' DESC 'Netscape def
objectClasses: ( 2.16.840.1.113730.3.2.1 NAME 'changeLogEntry' DESC 'LDAP changelog objectclass' SUP top MUST ( targetdn $ changeTime $ changenumber $ changeType ) MAY ( changes $ newrdn $ deleteoldrdn $ newsuperior ) X-ORIGIN 'Changelog Internet Draft' )
objectClasses: ( 2.16.840.1.113730.3.2.6 NAME 'referral' DESC 'LDAP referrals objectclass' SUP top MAY ( ref ) X-ORIGIN 'LDAPv3 referrals Internet Draft' )
objectClasses: ( 2.16.840.1.113730.3.2.12 NAME 'passwordObject' DESC 'Netscape defined password policy objectclass' SUP top MAY ( pwdpolicysubentry $ passwordExpirationTime $ passwordExpWarned $ passwordRetryCount $ retryCountResetTime $ accountUnlockTime $ passwordHistory $ passwordAllowChangeTime $ passwordGraceUserTime ) X-ORIGIN 'Netscape Directory Server' )
-objectClasses: ( 2.16.840.1.113730.3.2.13 NAME 'passwordPolicy' DESC 'Netscape defined password policy objectclass' SUP top MAY ( passwordMaxAge $ passwordExp $ passwordMinLength $ passwordKeepHistory $ passwordInHistory $ passwordChange $ passwordWarning $ passwordLockout $ passwordMaxFailure $ passwordResetDuration $ passwordUnlock $ passwordLockoutDuration $ passwordCheckSyntax $ passwordMustChange $ passwordStorageScheme $ passwordMinAge $ passwordResetFailureCount $ passwordGraceLimit $ passwordMinDigits $ passwordMinAlphas $ passwordMinUppers $ passwordMinLowers $ passwordMinSpecials $ passwordMin8bit $ passwordMaxRepeats $ passwordMinCategories $ passwordMinTokenLength ) X-ORIGIN 'Netscape Directory Server' )
+objectClasses: ( 2.16.840.1.113730.3.2.13 NAME 'passwordPolicy' DESC 'Netscape defined password policy objectclass' SUP top MAY ( passwordMaxAge $ passwordExp $ passwordMinLength $ passwordKeepHistory $ passwordInHistory $ passwordChange $ passwordWarning $ passwordLockout $ passwordMaxFailure $ passwordResetDuration $ passwordUnlock $ passwordLockoutDuration $ passwordCheckSyntax $ passwordMustChange $ passwordStorageScheme $ passwordMinAge $ passwordResetFailureCount $ passwordGraceLimit $ passwordMinDigits $ passwordMinAlphas $ passwordMinUppers $ passwordMinLowers $ passwordMinSpecials $ passwordMin8bit $ passwordMaxRepeats $ passwordMinCategories $ passwordMinTokenLength $ passwordTrackUpdateTime ) X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.30 NAME 'glue' DESC 'Netscape defined objectclass' SUP top X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.32 NAME 'netscapeMachineData' DESC 'Netscape defined objectclass' SUP top X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.38 NAME 'vlvSearch' DESC 'Netscape defined objectclass' SUP top MUST ( cn $ vlvBase $ vlvScope $ vlvFilter ) MAY ( multiLineDescription ) X-ORIGIN 'Netscape Directory Server' )
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
index 4736e82..04ad2ce 100644
--- a/ldap/servers/slapd/pw.c
+++ b/ldap/servers/slapd/pw.c
@@ -1628,10 +1628,13 @@ new_passwdPolicy(Slapi_PBlock *pb, const char *dn)
"--local policy entry not found\n", dn);
goto done;
}
-
+
/* set the default passwordLegacyPolicy setting */
pwdpolicy->pw_is_legacy = 1;
+ /* set passwordTrackUpdateTime */
+ pwdpolicy->pw_track_update_time = slapdFrontendConfig->pw_policy.pw_track_update_time;
+
for (slapi_entry_first_attr(pw_entry, &attr); attr;
slapi_entry_next_attr(pw_entry, attr, &attr))
{
11 years, 6 months