ITS#9264 add an optional lock to slapo-unique

This commit is contained in:
Howard Chu 2020-05-22 15:08:20 +01:00
parent 57d5aefecf
commit 9183abe62c
2 changed files with 92 additions and 15 deletions

View File

@ -39,7 +39,7 @@ They should appear after the
.B overlay
directive.
.TP
.B unique_uri <[strict ][ignore ]URI[URI...]...>
.B unique_uri <[strict ][ignore ][serialize ]URI[URI...]...>
Configure the base, attributes, scope, and filter for uniqueness
checking. Multiple URIs may be specified within a domain,
allowing complex selections of objects. Multiple
@ -50,9 +50,10 @@ attributes will create independent domains, each with their own
independent lists of URIs and ignore/strict settings.
Keywords
.B strict
.BR strict ,
.BR ignore ,
and
.B ignore
.B serialize
have to be enclosed in quotes (") together with the URI.
The LDAP URI syntax is a subset of
@ -119,6 +120,17 @@ mode extends the concept of uniqueness to include null values, such
that only one attribute within a subtree will be allowed to have a
null value. Strictness applies to all URIs within a uniqueness
domain, but some domains may be strict while others are not.
It is possible to enforce strict serialization of modifications by
prepending the keyword
.B serialize.
By default, no serialization is performed, so multiple modifications
occurring nearly simultaneously may see incomplete uniqueness results.
Using
.B serialize
will force individual write operations to fully complete before allowing
any others to proceed, to ensure that each operation's uniqueness checks
are consistent.
.LP
It is not possible to set both URIs and legacy slapo\-unique configuration
parameters simultaneously. In general, the legacy configuration options

View File

@ -58,12 +58,14 @@ typedef struct unique_domain_s {
struct unique_domain_uri_s *uri;
char ignore; /* polarity of attributes */
char strict; /* null considered unique too */
char serial; /* serialize execution */
} unique_domain;
typedef struct unique_data_s {
struct unique_domain_s *domains;
struct unique_domain_s *legacy;
char legacy_strict_set;
ldap_pvt_thread_mutex_t serial_mutex;
} unique_data;
typedef struct unique_counter_s {
@ -76,7 +78,7 @@ enum {
UNIQUE_IGNORE,
UNIQUE_ATTR,
UNIQUE_STRICT,
UNIQUE_URI
UNIQUE_URI,
};
static ConfigDriver unique_cf_base;
@ -315,7 +317,7 @@ unique_new_domain_uri_basic ( unique_domain_uri **urip,
*
* domain_specs look like
*
* [strict ][ignore ]uri[[ uri]...]
* [strict ][ignore ][serialize ]uri[[ uri]...]
* e.g. "ldap:///ou=foo,o=bar?uid?sub ldap:///ou=baz,o=bar?uid?sub"
* "strict ldap:///ou=accounts,o=bar?uid,uidNumber?one"
* etc
@ -346,6 +348,11 @@ unique_new_domain ( unique_domain **domainp,
domain->ignore = 1;
uri_start += STRLENOF( "ignore " );
}
if ( strncasecmp ( uri_start, "serialize ",
STRLENOF( "serialize " ) ) == 0 ) {
domain->serial = 1;
uri_start += STRLENOF( "serialize " );
}
if ( strncasecmp ( uri_start, "strict ",
STRLENOF( "strict " ) ) == 0 ) {
domain->strict = 1;
@ -644,11 +651,7 @@ unique_cf_strict( ConfigArgs *c )
* and missing is necessary to add olcUniqueURIs...
*/
if ( private->legacy_strict_set ) {
struct berval bv;
bv.bv_val = legacy->strict ? "TRUE" : "FALSE";
bv.bv_len = legacy->strict ?
STRLENOF("TRUE") :
STRLENOF("FALSE");
struct berval bv = legacy->strict ? slap_true_bv : slap_false_bv;
value_add_one ( &c->rvalue_vals, &bv );
}
rc = 0;
@ -789,11 +792,13 @@ unique_db_init(
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
unique_data **privatep = (unique_data **) &on->on_bi.bi_private;
unique_data *private;
Debug(LDAP_DEBUG_TRACE, "==> unique_db_init\n" );
*privatep = ch_calloc ( 1, sizeof ( unique_data ) );
private = ch_calloc ( 1, sizeof ( unique_data ) );
ldap_pvt_thread_mutex_init( &private->serial_mutex );
on->on_bi.bi_private = private;
return 0;
}
@ -805,8 +810,7 @@ unique_db_destroy(
)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
unique_data **privatep = (unique_data **) &on->on_bi.bi_private;
unique_data *private = *privatep;
unique_data *private = on->on_bi.bi_private;
Debug(LDAP_DEBUG_TRACE, "==> unique_db_destroy\n" );
@ -816,8 +820,9 @@ unique_db_destroy(
unique_free_domain ( domains );
unique_free_domain ( legacy );
ldap_pvt_thread_mutex_destroy( &private->serial_mutex );
ch_free ( private );
*privatep = NULL;
on->on_bi.bi_private = NULL;
}
return 0;
@ -1025,6 +1030,21 @@ unique_search(
return(rc);
}
static int
unique_unlock(
Operation *op,
SlapReply *rs
)
{
slap_callback *sc = op->o_callback;
unique_data *private = sc->sc_private;
ldap_pvt_thread_mutex_unlock( &private->serial_mutex );
op->o_callback = sc->sc_next;
op->o_tmpfree( sc, op->o_tmpmemctx );
return 0;
}
static int
unique_add(
Operation *op,
@ -1041,6 +1061,7 @@ unique_add(
char *key, *kp;
struct berval bvkey;
int rc = SLAP_CB_CONTINUE;
int locked = 0;
Debug(LDAP_DEBUG_TRACE, "==> unique_add <%s>\n",
op->o_req_dn.bv_val );
@ -1100,6 +1121,9 @@ unique_add(
/* skip this domain-uri if it isn't involved */
if ( !ks ) continue;
if ( domain->serial && !locked )
ldap_pvt_thread_mutex_lock( &private->serial_mutex );
/* terminating NUL */
ks += sizeof("(|)");
@ -1150,6 +1174,17 @@ unique_add(
if ( rc != SLAP_CB_CONTINUE ) break;
}
if ( locked ) {
if ( rc != SLAP_CB_CONTINUE ) {
ldap_pvt_thread_mutex_unlock( &private->serial_mutex );
} else {
slap_callback *cb = op->o_tmpcalloc( 1, sizeof(slap_callback), op->o_tmpmemctx );
cb->sc_cleanup = unique_unlock;
cb->sc_private = private;
cb->sc_next = op->o_callback;
op->o_callback = cb;
}
}
return rc;
}
@ -1171,6 +1206,7 @@ unique_modify(
char *key, *kp;
struct berval bvkey;
int rc = SLAP_CB_CONTINUE;
int locked = 0;
Debug(LDAP_DEBUG_TRACE, "==> unique_modify <%s>\n",
op->o_req_dn.bv_val );
@ -1223,6 +1259,9 @@ unique_modify(
/* skip this domain-uri if it isn't involved */
if ( !ks ) continue;
if ( domain->serial && !locked )
ldap_pvt_thread_mutex_lock( &private->serial_mutex );
/* terminating NUL */
ks += sizeof("(|)");
@ -1275,6 +1314,17 @@ unique_modify(
if ( rc != SLAP_CB_CONTINUE ) break;
}
if ( locked ) {
if ( rc != SLAP_CB_CONTINUE ) {
ldap_pvt_thread_mutex_unlock( &private->serial_mutex );
} else {
slap_callback *cb = op->o_tmpcalloc( 1, sizeof(slap_callback), op->o_tmpmemctx );
cb->sc_cleanup = unique_unlock;
cb->sc_private = private;
cb->sc_next = op->o_callback;
op->o_callback = cb;
}
}
return rc;
}
@ -1297,6 +1347,7 @@ unique_modrdn(
LDAPRDN newrdn;
struct berval bv[2];
int rc = SLAP_CB_CONTINUE;
int locked = 0;
Debug(LDAP_DEBUG_TRACE, "==> unique_modrdn <%s> <%s>\n",
op->o_req_dn.bv_val, op->orr_newrdn.bv_val );
@ -1374,6 +1425,9 @@ unique_modrdn(
/* skip this domain if it isn't involved */
if ( !ks ) continue;
if ( domain->serial && !locked )
ldap_pvt_thread_mutex_lock( &private->serial_mutex );
/* terminating NUL */
ks += sizeof("(|)");
@ -1426,6 +1480,17 @@ unique_modrdn(
if ( rc != SLAP_CB_CONTINUE ) break;
}
if ( locked ) {
if ( rc != SLAP_CB_CONTINUE ) {
ldap_pvt_thread_mutex_unlock( &private->serial_mutex );
} else {
slap_callback *cb = op->o_tmpcalloc( 1, sizeof(slap_callback), op->o_tmpmemctx );
cb->sc_cleanup = unique_unlock;
cb->sc_private = private;
cb->sc_next = op->o_callback;
op->o_callback = cb;
}
}
return rc;
}