ldap/schema/02common.ldif | 1 ldap/servers/slapd/back-ldbm/ancestorid.c | 18 +- ldap/servers/slapd/back-ldbm/back-ldbm.h | 3 ldap/servers/slapd/back-ldbm/filterindex.c | 142 +++++++++++--------- ldap/servers/slapd/back-ldbm/idl_new.c | 30 ++-- ldap/servers/slapd/back-ldbm/idl_shim.c | 17 +- ldap/servers/slapd/back-ldbm/import-threads.c | 2 ldap/servers/slapd/back-ldbm/index.c | 49 ++++++ ldap/servers/slapd/back-ldbm/ldbm_config.c | 76 ++++++---- ldap/servers/slapd/back-ldbm/ldbm_config.h | 2 ldap/servers/slapd/back-ldbm/ldbm_instance_config.c | 20 -- ldap/servers/slapd/back-ldbm/ldbm_search.c | 26 +++ ldap/servers/slapd/back-ldbm/proto-back-ldbm.h | 8 - ldap/servers/slapd/back-ldbm/start.c | 12 + 14 files changed, 273 insertions(+), 133 deletions(-)
New commits: commit c21515b1577d5e71fddc20b91bae7abfda6c90e1 Author: Rich Megginson rmeggins@redhat.com Date: Thu Sep 29 11:36:20 2011 -0600
Bug 742324 - allow nsslapd-idlistscanlimit to be set dynamically and per-user
https://bugzilla.redhat.com/show_bug.cgi?id=742324 Resolves: bug 742324 Bug Description: allow nsslapd-idlistscanlimit to be set dynamically and per-user Reviewed by: nhosoi, nkinder (Thanks!) Branch: master Fix Description: Changed the ldbm_config for idlistscanlimit to allow running change. Added a new attribute nsIDListScanLimit that works just like nsLookThroughLimit for user entries. For each search operation, calculate the idlistscanlimit to use based on any nsIDListScanLimit or database config. The biggest change was to extend the internal database API to allow the idlistscanlimit (aka allidslimit) to be passed down into the lowest level of the code where it is used. Platforms tested: RHEL6 x86_64 Flag Day: no Doc impact: Yes - will need to document how nsIDListScanLimit and nsslapd-idlistscanlimit work now
diff --git a/ldap/schema/02common.ldif b/ldap/schema/02common.ldif index 52c837a..0193091 100644 --- a/ldap/schema/02common.ldif +++ b/ldap/schema/02common.ldif @@ -123,6 +123,7 @@ attributeTypes: ( 2.16.840.1.113730.3.1.570 NAME 'nsLookThroughLimit' DESC 'Bind attributeTypes: ( 2.16.840.1.113730.3.1.571 NAME 'nsSizeLimit' DESC 'Binder-based search operation size limit (entries)' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE USAGE directoryOperation X-ORIGIN 'Netscape Directory Server' ) attributeTypes: ( 2.16.840.1.113730.3.1.572 NAME 'nsTimeLimit' DESC 'Binder-based search operation time limit (seconds)' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE USAGE directoryOperation X-ORIGIN 'Netscape Directory Server' ) attributeTypes: ( 2.16.840.1.113730.3.1.573 NAME 'nsIdleTimeout' DESC 'Binder-based connection idle timeout (seconds)' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE USAGE directoryOperation X-ORIGIN 'Netscape Directory Server' ) +attributeTypes: ( 2.16.840.1.113730.3.1.2106 NAME 'nsIDListScanLimit' DESC 'Binder-based search operation ID list scan limit (candidate entries)' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE USAGE directoryOperation X-ORIGIN 'Netscape Directory Server' ) attributeTypes: ( 2.16.840.1.113730.3.1.574 NAME 'nsRole' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 NO-USER-MODIFICATION USAGE directoryOperation X-ORIGIN 'Netscape Directory Server' ) attributeTypes: ( 2.16.840.1.113730.3.1.575 NAME 'nsRoleDN' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 USAGE directoryOperation X-ORIGIN 'Netscape Directory Server' ) attributeTypes: ( 2.16.840.1.113730.3.1.576 NAME 'nsRoleFilter' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' ) diff --git a/ldap/servers/slapd/back-ldbm/ancestorid.c b/ldap/servers/slapd/back-ldbm/ancestorid.c index 43a30b8..1e90871 100644 --- a/ldap/servers/slapd/back-ldbm/ancestorid.c +++ b/ldap/servers/slapd/back-ldbm/ancestorid.c @@ -643,7 +643,7 @@ static IDList *idl_union_allids(backend *be, struct attrinfo *ai, IDList *a, IDL if (!idl_get_idl_new()) { if (a != NULL && b != NULL) { if (ALLIDS( a ) || ALLIDS( b ) || - (IDL_NIDS(a) + IDL_NIDS(b) > idl_get_allidslimit(ai))) { + (IDL_NIDS(a) + IDL_NIDS(b) > idl_get_allidslimit(ai, 0))) { return( idl_allids( be ) ); } } @@ -975,11 +975,12 @@ int ldbm_ancestorid_move_subtree( return ret; }
-int ldbm_ancestorid_read( +int ldbm_ancestorid_read_ext( backend *be, back_txn *txn, ID id, - IDList **idl + IDList **idl, + int allidslimit ) { int ret = 0; @@ -989,8 +990,17 @@ int ldbm_ancestorid_read( bv.bv_val = keybuf; bv.bv_len = PR_snprintf(keybuf, sizeof(keybuf), "%lu", (u_long)id);
- *idl = index_read(be, LDBM_ANCESTORID_STR, indextype_EQUALITY, &bv, txn, &ret); + *idl = index_read_ext_allids(be, LDBM_ANCESTORID_STR, indextype_EQUALITY, &bv, txn, &ret, NULL, allidslimit);
return ret; }
+int ldbm_ancestorid_read( + backend *be, + back_txn *txn, + ID id, + IDList **idl +) +{ + return ldbm_ancestorid_read_ext(be, txn, id, idl, 0); +} diff --git a/ldap/servers/slapd/back-ldbm/back-ldbm.h b/ldap/servers/slapd/back-ldbm/back-ldbm.h index f9939d4..e6cab21 100644 --- a/ldap/servers/slapd/back-ldbm/back-ldbm.h +++ b/ldap/servers/slapd/back-ldbm/back-ldbm.h @@ -634,6 +634,7 @@ struct ldbminfo { int li_fat_lock; /* 608146 -- make this configurable, first */ int li_legacy_errcode; /* 615428 -- in case legacy err code is expected */ Slapi_Counter *li_global_usn_counter; /* global USN counter */ + int li_reslimit_allids_handle; /* allids aka idlistscan */ };
/* li_flags could store these bits defined in ../slapi-plugin.h @@ -801,6 +802,8 @@ typedef struct _back_search_result_set
/* Name of attribute type used for binder-based look through limit */ #define LDBM_LOOKTHROUGHLIMIT_AT "nsLookThroughLimit" +/* Name of attribute type used for binder-based look through limit */ +#define LDBM_ALLIDSLIMIT_AT "nsIDListScanLimit"
/* OIDs for attribute types used internally */ #define LDBM_ENTRYDN_OID "2.16.840.1.113730.3.1.602" diff --git a/ldap/servers/slapd/back-ldbm/filterindex.c b/ldap/servers/slapd/back-ldbm/filterindex.c index eacb6ef..d214c54 100644 --- a/ldap/servers/slapd/back-ldbm/filterindex.c +++ b/ldap/servers/slapd/back-ldbm/filterindex.c @@ -50,11 +50,11 @@ extern const char *indextype_EQUALITY; extern const char *indextype_APPROX; extern const char *indextype_SUB;
-static IDList *ava_candidates(Slapi_PBlock *pb, backend *be, Slapi_Filter *f, int ftype, Slapi_Filter *nextf, int range, int *err); -static IDList *presence_candidates(Slapi_PBlock *pb, backend *be, Slapi_Filter *f, int *err); -static IDList *extensible_candidates(Slapi_PBlock *pb, backend *be, Slapi_Filter *f, int *err); -static IDList *list_candidates(Slapi_PBlock *pb, backend *be, const char *base, Slapi_Filter *flist, int ftype, int *err); -static IDList *substring_candidates(Slapi_PBlock *pb, backend *be, Slapi_Filter *f, int *err); +static IDList *ava_candidates(Slapi_PBlock *pb, backend *be, Slapi_Filter *f, int ftype, Slapi_Filter *nextf, int range, int *err, int allidslimit); +static IDList *presence_candidates(Slapi_PBlock *pb, backend *be, Slapi_Filter *f, int *err, int allidslimit); +static IDList *extensible_candidates(Slapi_PBlock *pb, backend *be, Slapi_Filter *f, int *err, int allidslimit); +static IDList *list_candidates(Slapi_PBlock *pb, backend *be, const char *base, Slapi_Filter *flist, int ftype, int *err, int allidslimit); +static IDList *substring_candidates(Slapi_PBlock *pb, backend *be, Slapi_Filter *f, int *err, int allidslimit); static IDList * range_candidates( Slapi_PBlock *pb, backend *be, @@ -62,7 +62,8 @@ static IDList * range_candidates( struct berval *low_val, struct berval *high_val, int *err, - const Slapi_Attr *sattr + const Slapi_Attr *sattr, + int allidslimit ); static IDList * keys2idl( @@ -72,18 +73,20 @@ keys2idl( Slapi_Value **ivals, int *err, int *unindexed, - back_txn *txn + back_txn *txn, + int allidslimit );
IDList * -filter_candidates( +filter_candidates_ext( Slapi_PBlock *pb, backend *be, const char *base, Slapi_Filter *f, Slapi_Filter *nextf, int range, - int *err + int *err, + int allidslimit ) { struct ldbminfo *li = (struct ldbminfo *) be->be_database->plg_private; @@ -91,7 +94,11 @@ filter_candidates( int ftype;
LDAPDebug( LDAP_DEBUG_TRACE, "=> filter_candidates\n", 0, 0, 0 ); - + + if (!allidslimit) { + allidslimit = compute_allids_limit(pb, li); + } + /* check if this is to be serviced by a virtual index */ if(INDEX_FILTER_EVALUTED == index_subsys_evaluate_filter(f, (Slapi_DN*)slapi_be_getsuffix(be, 0), (IndexEntryList**)&result)) { @@ -119,50 +126,50 @@ filter_candidates( switch ( (ftype = slapi_filter_get_choice( f )) ) { case LDAP_FILTER_EQUALITY: LDAPDebug( LDAP_DEBUG_FILTER, "\tEQUALITY\n", 0, 0, 0 ); - result = ava_candidates( pb, be, f, LDAP_FILTER_EQUALITY, nextf, range, err ); + result = ava_candidates( pb, be, f, LDAP_FILTER_EQUALITY, nextf, range, err, allidslimit ); break;
case LDAP_FILTER_SUBSTRINGS: LDAPDebug( LDAP_DEBUG_FILTER, "\tSUBSTRINGS\n", 0, 0, 0 ); - result = substring_candidates( pb, be, f, err ); + result = substring_candidates( pb, be, f, err, allidslimit ); break;
case LDAP_FILTER_GE: LDAPDebug( LDAP_DEBUG_FILTER, "\tGE\n", 0, 0, 0 ); result = ava_candidates( pb, be, f, LDAP_FILTER_GE, nextf, range, - err ); + err, allidslimit ); break;
case LDAP_FILTER_LE: LDAPDebug( LDAP_DEBUG_FILTER, "\tLE\n", 0, 0, 0 ); result = ava_candidates( pb, be, f, LDAP_FILTER_LE, nextf, range, - err ); + err, allidslimit ); break;
case LDAP_FILTER_PRESENT: LDAPDebug( LDAP_DEBUG_FILTER, "\tPRESENT\n", 0, 0, 0 ); - result = presence_candidates( pb, be, f, err ); + result = presence_candidates( pb, be, f, err, allidslimit ); break;
case LDAP_FILTER_APPROX: LDAPDebug( LDAP_DEBUG_FILTER, "\tAPPROX\n", 0, 0, 0 ); result = ava_candidates( pb, be, f, LDAP_FILTER_APPROX, nextf, - range, err ); + range, err, allidslimit ); break;
case LDAP_FILTER_EXTENDED: LDAPDebug( LDAP_DEBUG_FILTER, "\tEXTENSIBLE\n", 0, 0, 0 ); - result = extensible_candidates( pb, be, f, err ); + result = extensible_candidates( pb, be, f, err, allidslimit ); break;
case LDAP_FILTER_AND: LDAPDebug( LDAP_DEBUG_FILTER, "\tAND\n", 0, 0, 0 ); - result = list_candidates( pb, be, base, f, LDAP_FILTER_AND, err ); + result = list_candidates( pb, be, base, f, LDAP_FILTER_AND, err, allidslimit ); break;
case LDAP_FILTER_OR: LDAPDebug( LDAP_DEBUG_FILTER, "\tOR\n", 0, 0, 0 ); - result = list_candidates( pb, be, base, f, LDAP_FILTER_OR, err ); + result = list_candidates( pb, be, base, f, LDAP_FILTER_OR, err, allidslimit ); break;
case LDAP_FILTER_NOT: @@ -182,6 +189,20 @@ filter_candidates( return( result ); }
+IDList * +filter_candidates( + Slapi_PBlock *pb, + backend *be, + const char *base, + Slapi_Filter *f, + Slapi_Filter *nextf, + int range, + int *err +) +{ + return filter_candidates_ext(pb, be, base, f, nextf, range, err, 0); +} + static IDList * ava_candidates( Slapi_PBlock *pb, @@ -190,7 +211,8 @@ ava_candidates( int ftype, Slapi_Filter *nextf, int range, - int *err + int *err, + int allidslimit ) { char *type, *indextype = NULL; @@ -238,13 +260,13 @@ ava_candidates(
switch ( ftype ) { case LDAP_FILTER_GE: - idl = range_candidates(pb, be, type, bval, NULL, err, &sattr); + idl = range_candidates(pb, be, type, bval, NULL, err, &sattr, allidslimit); LDAPDebug( LDAP_DEBUG_TRACE, "<= ava_candidates %lu\n", (u_long)IDL_NIDS(idl), 0, 0 ); goto done; break; case LDAP_FILTER_LE: - idl = range_candidates(pb, be, type, NULL, bval, err, &sattr); + idl = range_candidates(pb, be, type, NULL, bval, err, &sattr, allidslimit); LDAPDebug( LDAP_DEBUG_TRACE, "<= ava_candidates %lu\n", (u_long)IDL_NIDS(idl), 0, 0 ); goto done; @@ -288,7 +310,7 @@ ava_candidates( ivals=ptr;
slapi_attr_assertion2keys_ava_sv( &sattr, &tmp, (Slapi_Value ***)&ivals, LDAP_FILTER_EQUALITY_FAST); - idl = keys2idl( be, type, indextype, ivals, err, &unindexed, &txn ); + idl = keys2idl( be, type, indextype, ivals, err, &unindexed, &txn, allidslimit ); if ( unindexed ) { unsigned int opnote = SLAPI_OP_NOTE_UNINDEXED; slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote ); @@ -320,7 +342,7 @@ ava_candidates( idl = idl_allids( be ); goto done; } - idl = keys2idl( be, type, indextype, ivals, err, &unindexed, &txn ); + idl = keys2idl( be, type, indextype, ivals, err, &unindexed, &txn, allidslimit ); if ( unindexed ) { unsigned int opnote = SLAPI_OP_NOTE_UNINDEXED; slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote ); @@ -340,7 +362,8 @@ presence_candidates( Slapi_PBlock *pb, backend *be, Slapi_Filter *f, - int *err + int *err, + int allidslimit ) { char *type; @@ -356,8 +379,8 @@ presence_candidates( return( NULL ); } slapi_pblock_get(pb, SLAPI_TXN, &txn.back_txn_txn); - idl = index_read_ext( be, type, indextype_PRESENCE, - NULL, &txn, err, &unindexed ); + idl = index_read_ext_allids( be, type, indextype_PRESENCE, + NULL, &txn, err, &unindexed, allidslimit );
if ( unindexed ) { unsigned int opnote = SLAPI_OP_NOTE_UNINDEXED; @@ -371,9 +394,9 @@ presence_candidates( "fallback to eq index as pres index gave allids\n", 0, 0, 0); idl_free(idl); - idl = index_range_read(pb, be, type, indextype_EQUALITY, + idl = index_range_read_ext(pb, be, type, indextype_EQUALITY, SLAPI_OP_GREATER_OR_EQUAL, - NULL, NULL, 0, &txn, err); + NULL, NULL, 0, &txn, err, allidslimit); }
LDAPDebug( LDAP_DEBUG_TRACE, "<= presence_candidates %lu\n", @@ -386,7 +409,8 @@ extensible_candidates( Slapi_PBlock *glob_pb, backend *be, Slapi_Filter *f, - int *err + int *err, + int allidslimit ) { IDList* idl = NULL; @@ -462,10 +486,10 @@ extensible_candidates( { int unindexed = 0; IDList* idl3 = (mrOP == SLAPI_OP_EQUAL) ? - index_read_ext(be, mrTYPE, mrOID, *key, &txn, - err, &unindexed) : - index_range_read (pb, be, mrTYPE, mrOID, mrOP, - *key, NULL, 0, &txn, err); + index_read_ext_allids(be, mrTYPE, mrOID, *key, &txn, + err, &unindexed, allidslimit) : + index_range_read_ext(pb, be, mrTYPE, mrOID, mrOP, + *key, NULL, 0, &txn, err, allidslimit); if ( unindexed ) { unsigned int opnote = SLAPI_OP_NOTE_UNINDEXED; slapi_pblock_set( glob_pb, @@ -537,7 +561,8 @@ range_candidates( struct berval *low_val, struct berval *high_val, int *err, - const Slapi_Attr *sattr + const Slapi_Attr *sattr, + int allidslimit ) { IDList *idl = NULL; @@ -572,17 +597,17 @@ range_candidates( }
if (low == NULL) { - idl = index_range_read(pb, be, type, (char*)indextype_EQUALITY, - SLAPI_OP_LESS_OR_EQUAL, - high, NULL, 0, &txn, err); + idl = index_range_read_ext(pb, be, type, (char*)indextype_EQUALITY, + SLAPI_OP_LESS_OR_EQUAL, + high, NULL, 0, &txn, err, allidslimit); } else if (high == NULL) { - idl = index_range_read(pb, be, type, (char*)indextype_EQUALITY, - SLAPI_OP_GREATER_OR_EQUAL, - low, NULL, 0, &txn, err); + idl = index_range_read_ext(pb, be, type, (char*)indextype_EQUALITY, + SLAPI_OP_GREATER_OR_EQUAL, + low, NULL, 0, &txn, err, allidslimit); } else { - idl = index_range_read(pb, be, type, (char*)indextype_EQUALITY, - SLAPI_OP_GREATER_OR_EQUAL, - low, high, 1, &txn, err); + idl = index_range_read_ext(pb, be, type, (char*)indextype_EQUALITY, + SLAPI_OP_GREATER_OR_EQUAL, + low, high, 1, &txn, err, allidslimit); }
done: @@ -602,7 +627,8 @@ list_candidates( const char *base, Slapi_Filter *flist, int ftype, - int *err + int *err, + int allidslimit ) { IDList *idl, *tmp, *tmp2; @@ -712,7 +738,7 @@ list_candidates( Slapi_Attr sattr;
slapi_attr_init(&sattr, tpairs[0]); - idl = range_candidates(pb, be, tpairs[0], vpairs[0], vpairs[1], err, &sattr); + idl = range_candidates(pb, be, tpairs[0], vpairs[0], vpairs[1], err, &sattr, allidslimit); attr_done(&sattr); LDAPDebug( LDAP_DEBUG_TRACE, "<= list_candidates %lu\n", (u_long)IDL_NIDS(idl), 0, 0 ); @@ -741,7 +767,7 @@ list_candidates( /* Fetch the IDL for foo */ /* Later we'll remember to call idl_notin() */ LDAPDebug( LDAP_DEBUG_TRACE,"NOT filter\n", 0, 0, 0 ); - tmp = ava_candidates( pb, be, slapi_filter_list_first(f), LDAP_FILTER_EQUALITY, nextf, range, err ); + tmp = ava_candidates( pb, be, slapi_filter_list_first(f), LDAP_FILTER_EQUALITY, nextf, range, err, allidslimit ); } else { if (fpairs[0] == f) { @@ -753,7 +779,7 @@ list_candidates(
slapi_attr_init(&sattr, tpairs[0]); tmp = range_candidates(pb, be, tpairs[0], - vpairs[0], vpairs[1], err, &sattr); + vpairs[0], vpairs[1], err, &sattr, allidslimit); attr_done(&sattr); if (tmp == NULL && ftype == LDAP_FILTER_AND) { @@ -765,7 +791,7 @@ list_candidates( } } /* Proceed as normal */ - else if ( (tmp = filter_candidates( pb, be, base, f, nextf, range, err )) + else if ( (tmp = filter_candidates_ext( pb, be, base, f, nextf, range, err, allidslimit )) == NULL && ftype == LDAP_FILTER_AND ) { LDAPDebug( LDAP_DEBUG_TRACE, "<= list_candidates NULL\n", 0, 0, 0 ); @@ -802,9 +828,7 @@ list_candidates( break; } else { Slapi_Operation *operation; - struct ldbminfo *li; slapi_pblock_get( pb, SLAPI_OPERATION, &operation ); - slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
idl = idl_union( be, idl, tmp ); idl_free( tmp ); @@ -812,13 +836,11 @@ list_candidates( /* stop if we're already committed to an exhaustive * search. :( */ - /* PAGED RESULTS: if not Directory Manager, we strictly limit - * the idlist size by the lookthrough limit. + /* PAGED RESULTS: we strictly limit the idlist size by the allids (aka idlistscan) limit. */ if (operation->o_flags & OP_FLAG_PAGED_RESULTS) { int nids = IDL_NIDS(idl); - int lookthroughlimits = compute_lookthrough_limit( pb, li ); - if ( lookthroughlimits > 0 && nids > lookthroughlimits ) { + if ( allidslimit > 0 && nids > allidslimit ) { idl_free( idl ); idl = idl_allids( be ); } @@ -852,7 +874,8 @@ substring_candidates( Slapi_PBlock *pb, backend *be, Slapi_Filter *f, - int *err + int *err, + int allidslimit ) { char *type, *initial, *final; @@ -892,7 +915,7 @@ substring_candidates( * IDLists together. */ slapi_pblock_get(pb, SLAPI_TXN, &txn.back_txn_txn); - idl = keys2idl( be, type, indextype_SUB, ivals, err, &unindexed, &txn ); + idl = keys2idl( be, type, indextype_SUB, ivals, err, &unindexed, &txn, allidslimit ); if ( unindexed ) { slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote ); pagedresults_set_unindexed( pb->pb_conn ); @@ -912,7 +935,8 @@ keys2idl( Slapi_Value **ivals, int *err, int *unindexed, - back_txn *txn + back_txn *txn, + int allidslimit ) { IDList *idl; @@ -924,7 +948,7 @@ keys2idl( for ( i = 0; ivals[i] != NULL; i++ ) { IDList *idl2;
- idl2 = index_read_ext( be, type, indextype, slapi_value_get_berval(ivals[i]), txn, err, unindexed ); + idl2 = index_read_ext_allids( be, type, indextype, slapi_value_get_berval(ivals[i]), txn, err, unindexed, allidslimit );
#ifdef LDAP_DEBUG /* XXX if ( slapd_ldap_debug & LDAP_DEBUG_TRACE ) { XXX */ diff --git a/ldap/servers/slapd/back-ldbm/idl_new.c b/ldap/servers/slapd/back-ldbm/idl_new.c index 298d5e8..aa69960 100644 --- a/ldap/servers/slapd/back-ldbm/idl_new.c +++ b/ldap/servers/slapd/back-ldbm/idl_new.c @@ -102,18 +102,29 @@ int idl_new_get_tune() { return idl_tune; }
-size_t idl_new_get_allidslimit(struct attrinfo *a) +size_t idl_new_get_allidslimit(struct attrinfo *a, int allidslimit) { idl_private *priv = NULL;
+ if (allidslimit) { + return (size_t)allidslimit; + } + PR_ASSERT(NULL != a); PR_ASSERT(NULL != a->ai_idl);
priv = a->ai_idl; - + return priv->idl_allidslimit; }
+int idl_new_exceeds_allidslimit(size_t count, struct attrinfo *a, int allidslimit) +{ + size_t limit = idl_new_get_allidslimit(a, allidslimit); + return (limit != (size_t)-1) && (count > limit); +} + + /* routine to initialize the private data used by the IDL code per-attribute */ int idl_new_init_private(backend *be,struct attrinfo *a) { @@ -127,7 +138,7 @@ int idl_new_init_private(backend *be,struct attrinfo *a) if (NULL == priv) { return -1; /* Memory allocation failure */ } - priv->idl_allidslimit = li->li_allidsthreshold; + priv->idl_allidslimit = (size_t)li->li_allidsthreshold; /* Initialize the structure */ a->ai_idl = (void*)priv; return 0; @@ -150,7 +161,8 @@ IDList * idl_new_fetch( DBT *inkey, DB_TXN *txn, struct attrinfo *a, - int *flag_err + int *flag_err, + int allidslimit ) { int ret = 0; @@ -261,7 +273,7 @@ IDList * idl_new_fetch( #if defined(DB_ALLIDS_ON_READ) /* enforce the allids read limit */ if (NEW_IDL_NO_ALLID != *flag_err && - NULL != a && count > idl_new_get_allidslimit(a)) { + NULL != a && 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 */ @@ -289,7 +301,7 @@ IDList * idl_new_fetch( } #if defined(DB_ALLIDS_ON_READ) /* enforce the allids read limit */ - if (count > idl_new_get_allidslimit(a)) { + if (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 */ @@ -392,7 +404,7 @@ int idl_new_insert_key( key->data, 0, 0); goto error; } - if ((size_t)count > idl_new_get_allidslimit(a)) { + if ((size_t)count > idl_new_get_allidslimit(a, 0)) { LDAPDebug(LDAP_DEBUG_TRACE, "allidslimit exceeded for key %s\n", key->data, 0, 0); cursor->c_close(cursor); @@ -589,7 +601,7 @@ int idl_new_store_block( #if defined(DB_ALLIDS_ON_WRITE) /* allids check on input idl */ - if (ALLIDS(idl) || (idl->b_nids > (ID)idl_new_get_allidslimit(a))) { + if (ALLIDS(idl) || (idl->b_nids > (ID)idl_new_get_allidslimit(a, 0))) { return idl_new_store_allids(be, db, key, txn); } #endif @@ -638,7 +650,7 @@ int idl_new_store_block( key->data, 0, 0); goto error; } - if ((size_t)count > idl_new_get_allidslimit(a)) { + if ((size_t)count > idl_new_get_allidslimit(a, 0)) { LDAPDebug(LDAP_DEBUG_TRACE, "allidslimit exceeded for key %s\n", key->data, 0, 0); cursor->c_close(cursor); diff --git a/ldap/servers/slapd/back-ldbm/idl_shim.c b/ldap/servers/slapd/back-ldbm/idl_shim.c index 10d8618..8d4d48a 100644 --- a/ldap/servers/slapd/back-ldbm/idl_shim.c +++ b/ldap/servers/slapd/back-ldbm/idl_shim.c @@ -62,8 +62,8 @@ void idl_new_set_tune(int val); int idl_new_get_tune(); int idl_new_init_private(backend *be, struct attrinfo *a); int idl_new_release_private(struct attrinfo *a); -size_t idl_new_get_allidslimit(struct attrinfo *a); -IDList * idl_new_fetch( backend *be, DB* db, DBT *key, DB_TXN *txn, struct attrinfo *a, int *err ); +size_t idl_new_get_allidslimit(struct attrinfo *a, int allidslimit); +IDList * idl_new_fetch( backend *be, DB* db, DBT *key, DB_TXN *txn, struct attrinfo *a, int *err, int allidslimit ); int idl_new_insert_key( backend *be, DB* db, DBT *key, ID id, DB_TXN *txn, struct attrinfo *a,int *disposition ); int idl_new_delete_key( backend *be, DB *db, DBT *key, ID id, DB_TXN *txn, struct attrinfo *a ); int idl_new_store_block( backend *be,DB *db,DBT *key,IDList *idl,DB_TXN *txn,struct attrinfo *a); @@ -115,24 +115,29 @@ int idl_release_private(struct attrinfo *a) } }
-size_t idl_get_allidslimit(struct attrinfo *a) +size_t idl_get_allidslimit(struct attrinfo *a, int allidslimit) { if (idl_new) { - return idl_new_get_allidslimit(a); + return idl_new_get_allidslimit(a, allidslimit); } else { return idl_old_get_allidslimit(a); } }
-IDList * idl_fetch( backend *be, DB* db, DBT *key, DB_TXN *txn, struct attrinfo *a, int *err ) +IDList * idl_fetch_ext( backend *be, DB* db, DBT *key, DB_TXN *txn, struct attrinfo *a, int *err, int allidslimit ) { if (idl_new) { - return idl_new_fetch(be,db,key,txn,a,err); + return idl_new_fetch(be,db,key,txn,a,err,allidslimit); } else { return idl_old_fetch(be,db,key,txn,a,err); } }
+IDList * idl_fetch( backend *be, DB* db, DBT *key, DB_TXN *txn, struct attrinfo *a, int *err ) +{ + return idl_fetch_ext(be, db, key, txn, a, err, 0); +} + int idl_insert_key( backend *be, DB* db, DBT *key, ID id, DB_TXN *txn, struct attrinfo *a,int *disposition ) { if (idl_new) { diff --git a/ldap/servers/slapd/back-ldbm/import-threads.c b/ldap/servers/slapd/back-ldbm/import-threads.c index 5e5c001..207c470 100644 --- a/ldap/servers/slapd/back-ldbm/import-threads.c +++ b/ldap/servers/slapd/back-ldbm/import-threads.c @@ -1931,7 +1931,7 @@ foreman_do_parentid(ImportJob *job, FifoItem *fi, struct attrinfo *parentid_ai)
if (idl_disposition == IDL_INSERT_NOW_ALLIDS) { import_subcount_mother_init(job->mothers, parent_id, - idl_get_allidslimit(parentid_ai)+1); + idl_get_allidslimit(parentid_ai, 0)+1); } else if (idl_disposition == IDL_INSERT_ALLIDS) { import_subcount_mother_count(job->mothers, parent_id); } diff --git a/ldap/servers/slapd/back-ldbm/index.c b/ldap/servers/slapd/back-ldbm/index.c index 67be28d..c8be27a 100644 --- a/ldap/servers/slapd/back-ldbm/index.c +++ b/ldap/servers/slapd/back-ldbm/index.c @@ -811,16 +811,21 @@ index_read( * The unindexed flag can be used to distinguish between a * return of allids due to the attr not being indexed or * the value really being allids. + * You can pass in the value of the allidslimit (aka idlistscanlimit) + * with this version of the function + * if the value is 0, it will use the old method of getting the value + * from the attrinfo*. */ IDList * -index_read_ext( +index_read_ext_allids( backend *be, char *type, const char *indextype, const struct berval *val, back_txn *txn, int *err, - int *unindexed + int *unindexed, + int allidslimit ) { DB *db = NULL; @@ -945,7 +950,7 @@ index_read_ext( } for (retry_count = 0; retry_count < IDL_FETCH_RETRY_COUNT; retry_count++) { *err = NEW_IDL_DEFAULT; - idl = idl_fetch( be, db, &key, db_txn, ai, err ); + idl = idl_fetch_ext( be, db, &key, db_txn, ai, err, allidslimit ); if(*err == DB_LOCK_DEADLOCK) { ldbm_nasty("index read retrying transaction", 1045, *err); continue; @@ -974,6 +979,20 @@ index_read_ext( return( idl ); }
+IDList * +index_read_ext( + backend *be, + char *type, + const char *indextype, + const struct berval *val, + back_txn *txn, + int *err, + int *unindexed +) +{ + return index_read_ext_allids(be, type, indextype, val, txn, err, unindexed, 0); +} + /* This function compares two index keys. It is assumed that the values are already normalized, since they should have been when the index was created (by int_values2keys). @@ -1101,7 +1120,7 @@ error: }
IDList * -index_range_read( +index_range_read_ext( Slapi_PBlock *pb, backend *be, char *type, @@ -1111,7 +1130,8 @@ index_range_read( struct berval *nextval, int range, back_txn *txn, - int *err + int *err, + int allidslimit ) { struct ldbminfo *li = (struct ldbminfo *) be->be_database->plg_private; @@ -1427,7 +1447,7 @@ index_range_read( cur_key.flags = 0; for (retry_count = 0; retry_count < IDL_FETCH_RETRY_COUNT; retry_count++) { *err = NEW_IDL_DEFAULT; - tmp = idl_fetch( be, db, &cur_key, NULL, ai, err ); + tmp = idl_fetch_ext( be, db, &cur_key, NULL, ai, err, allidslimit ); if(*err == DB_LOCK_DEADLOCK) { ldbm_nasty("index_range_read retrying transaction", 1090, *err); continue; @@ -1494,6 +1514,23 @@ error: return( idl ); }
+IDList * +index_range_read( + Slapi_PBlock *pb, + backend *be, + char *type, + const char *indextype, + int operator, + struct berval *val, + struct berval *nextval, + int range, + back_txn *txn, + int *err +) +{ + return index_range_read_ext(pb, be, type, indextype, operator, val, nextval, range, txn, err, 0); +} + /* DBDB: this function is never actually called */ #if 0 static int diff --git a/ldap/servers/slapd/back-ldbm/ldbm_config.c b/ldap/servers/slapd/back-ldbm/ldbm_config.c index e265eaf..44c7ff9 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_config.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_config.c @@ -203,7 +203,7 @@ static int ldbm_config_allidsthreshold_set(void *arg, void *value, char *errorbu /* Do whatever we can to make sure the data is ok. */
/* Catch attempts to configure a stupidly low allidsthreshold */ - if (val < 100) { + if ((val > -1) && (val < 100)) { val = 100; }
@@ -1231,7 +1231,7 @@ static int ldbm_config_db_tx_max_set( static config_info ldbm_config[] = { {CONFIG_LOOKTHROUGHLIMIT, CONFIG_TYPE_INT, "5000", &ldbm_config_lookthroughlimit_get, &ldbm_config_lookthroughlimit_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE}, {CONFIG_MODE, CONFIG_TYPE_INT_OCTAL, "0600", &ldbm_config_mode_get, &ldbm_config_mode_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE}, - {CONFIG_IDLISTSCANLIMIT, CONFIG_TYPE_INT, "4000", &ldbm_config_allidsthreshold_get, &ldbm_config_allidsthreshold_set, CONFIG_FLAG_ALWAYS_SHOW}, + {CONFIG_IDLISTSCANLIMIT, CONFIG_TYPE_INT, "4000", &ldbm_config_allidsthreshold_get, &ldbm_config_allidsthreshold_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE}, {CONFIG_DIRECTORY, CONFIG_TYPE_STRING, "", &ldbm_config_directory_get, &ldbm_config_directory_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE|CONFIG_FLAG_SKIP_DEFAULT_SETTING}, {CONFIG_DBCACHESIZE, CONFIG_TYPE_SIZE_T, "10000000", &ldbm_config_dbcachesize_get, &ldbm_config_dbcachesize_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE}, {CONFIG_DBNCACHE, CONFIG_TYPE_INT, "0", &ldbm_config_dbncache_get, &ldbm_config_dbncache_set, CONFIG_FLAG_ALLOW_RUNNING_CHANGE}, diff --git a/ldap/servers/slapd/back-ldbm/ldbm_search.c b/ldap/servers/slapd/back-ldbm/ldbm_search.c index 43b4fab..94341c5 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_search.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_search.c @@ -96,6 +96,26 @@ compute_lookthrough_limit( Slapi_PBlock *pb, struct ldbminfo *li ) return( limit ); }
+int +compute_allids_limit( Slapi_PBlock *pb, struct ldbminfo *li ) +{ + Slapi_Connection *conn = NULL; + int limit; + + slapi_pblock_get( pb, SLAPI_CONNECTION, &conn); + + if ( slapi_reslimit_get_integer_limit( conn, + li->li_reslimit_allids_handle, &limit ) + != SLAPI_RESLIMIT_STATUS_SUCCESS ) { + PR_Lock(li->li_config_mutex); + limit = li->li_allidsthreshold; + PR_Unlock(li->li_config_mutex); + } + + return( limit ); +} + + /* don't free the berval, just clean it */ static void berval_done(struct berval *val) @@ -962,12 +982,14 @@ subtree_candidates( IDList *candidates; PRBool has_tombstone_filter; int isroot = 0; + struct ldbminfo *li = (struct ldbminfo *) be->be_database->plg_private; + int allidslimit = compute_allids_limit(pb, li);
/* make (|(originalfilter)(objectclass=referral)) */ ftop= create_subtree_filter(filter, managedsait, &focref, &forr);
/* Fetch a candidate list for the original filter */ - candidates = filter_candidates( pb, be, base, ftop, NULL, 0, err ); + candidates = filter_candidates_ext( pb, be, base, ftop, NULL, 0, err, allidslimit ); slapi_filter_free( forr, 0 ); slapi_filter_free( focref, 0 );
@@ -1000,7 +1022,7 @@ subtree_candidates( idl_free(tmp); idl_free(descendants); } else if (!has_tombstone_filter) { - *err = ldbm_ancestorid_read(be, &txn, e->ep_id, &descendants); + *err = ldbm_ancestorid_read_ext(be, &txn, e->ep_id, &descendants, allidslimit); idl_insert(&descendants, e->ep_id); candidates = idl_intersection(be, candidates, descendants); idl_free(tmp); diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h index a087a05..c30e987 100644 --- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h +++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h @@ -198,6 +198,7 @@ struct backentry * uniqueid2entry(backend *be, const char *uniqueid, * filterindex.c */ IDList * filter_candidates( Slapi_PBlock *pb, backend *be, const char *base, Slapi_Filter *f, Slapi_Filter *nextf, int range, int *err ); +IDList * filter_candidates_ext( Slapi_PBlock *pb, backend *be, const char *base, Slapi_Filter *f, Slapi_Filter *nextf, int range, int *err, int allidslimit );
/* * findentry.c @@ -242,6 +243,7 @@ void idl_insert(IDList **idl, ID id); int idl_delete( IDList **idl, ID id ); IDList * idl_allids( backend *be ); IDList * idl_fetch( backend *be, DB* db, DBT *key, DB_TXN *txn, struct attrinfo *a, int *err ); +IDList * idl_fetch_ext( backend *be, DB* db, DBT *key, DB_TXN *txn, struct attrinfo *a, int *err, int allidslimit ); int idl_insert_key( backend *be, DB* db, DBT *key, ID id, DB_TXN *txn, struct attrinfo *a,int *disposition ); int idl_delete_key( backend *be, DB *db, DBT *key, ID id, DB_TXN *txn, struct attrinfo *a ); IDList * idl_intersection( backend *be, IDList *a, IDList *b ); @@ -262,7 +264,7 @@ size_t idl_sizeof(IDList *idl); int idl_store_block(backend *be,DB *db,DBT *key,IDList *idl,DB_TXN *txn,struct attrinfo *a); void idl_set_tune(int val); int idl_get_tune(); -size_t idl_get_allidslimit(struct attrinfo *a); +size_t idl_get_allidslimit(struct attrinfo *a, int allidslimit); int idl_get_idl_new(); int idl_new_compare_dups( #if 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR >= 3200 @@ -284,7 +286,9 @@ int id_array_init(Id_Array *new_guy, int size);
IDList* index_read( backend *be, char *type, const char* indextype, const struct berval* val, back_txn *txn, int *err ); IDList* index_read_ext( backend *be, char *type, const char* indextype, const struct berval* val, back_txn *txn, int *err, int *unindexed ); +IDList* index_read_ext_allids( backend *be, char *type, const char* indextype, const struct berval* val, back_txn *txn, int *err, int *unindexed, int allidslimit ); IDList* index_range_read( Slapi_PBlock *pb, backend *be, char *type, const char* indextype, int ftype, struct berval* val, struct berval* nextval, int range, back_txn *txn, int *err ); +IDList* index_range_read_ext( Slapi_PBlock *pb, backend *be, char *type, const char* indextype, int ftype, struct berval* val, struct berval* nextval, int range, back_txn *txn, int *err, int allidslimit ); const char *encode( const struct berval* data, char buf[BUFSIZ] );
extern const char* indextype_PRESENCE; @@ -569,6 +573,7 @@ IDList* subtree_candidates(Slapi_PBlock *pb, backend *be, const char *base, cons void search_set_tune(struct ldbminfo *li,int val); int search_get_tune(struct ldbminfo *li); int compute_lookthrough_limit( Slapi_PBlock *pb, struct ldbminfo *li ); +int compute_allids_limit( Slapi_PBlock *pb, struct ldbminfo *li );
/* @@ -638,6 +643,7 @@ void replace_ldbm_config_value(char *conftype, char *val, struct ldbminfo *li); int ldbm_ancestorid_create_index(backend *be); int ldbm_ancestorid_index_entry(backend *be, struct backentry *e, int flags, back_txn *txn); int ldbm_ancestorid_read(backend *be, back_txn *txn, ID id, IDList **idl); +int ldbm_ancestorid_read_ext(backend *be, back_txn *txn, ID id, IDList **idl, int allidslimit); int ldbm_ancestorid_move_subtree( backend *be, const Slapi_DN *olddn, diff --git a/ldap/servers/slapd/back-ldbm/start.c b/ldap/servers/slapd/back-ldbm/start.c index 6c19c76..9e18086 100644 --- a/ldap/servers/slapd/back-ldbm/start.c +++ b/ldap/servers/slapd/back-ldbm/start.c @@ -81,7 +81,17 @@ ldbm_back_start( Slapi_PBlock *pb ) if ( slapi_reslimit_register( SLAPI_RESLIMIT_TYPE_INT, LDBM_LOOKTHROUGHLIMIT_AT, &li->li_reslimit_lookthrough_handle ) != SLAPI_RESLIMIT_STATUS_SUCCESS ) { - LDAPDebug( LDAP_DEBUG_ANY, "start: Resource limit registration failed\n", + LDAPDebug( LDAP_DEBUG_ANY, "start: Resource limit registration failed for lookthroughlimit\n", + 0, 0, 0 ); + return SLAPI_FAIL_GENERAL; + } + + /* register with the binder-based resource limit subsystem so that */ + /* allidslimit (aka idlistscanlimit) can be supported on a per-connection basis. */ + if ( slapi_reslimit_register( SLAPI_RESLIMIT_TYPE_INT, + LDBM_ALLIDSLIMIT_AT, &li->li_reslimit_allids_handle ) + != SLAPI_RESLIMIT_STATUS_SUCCESS ) { + LDAPDebug( LDAP_DEBUG_ANY, "start: Resource limit registration failed for allidslimit\n", 0, 0, 0 ); return SLAPI_FAIL_GENERAL; }
commit 015b31e7bc8e7072aa78ac33567c7873979cf622 Author: Rich Megginson rmeggins@redhat.com Date: Tue Sep 27 16:36:57 2011 -0600
Bug 741744 - MOD operations with chained delete/add get back error 53 on backend config
https://bugzilla.redhat.com/show_bug.cgi?id=741744 Resolves: bug 741744 Bug Description: MOD operations with chained delete/add get back error 53 on backend config Reviewed by: nkinder (Thanks!) Branch: master Fix Description: Allow ldbm config mods to use MOD_ADD and MOD_DELETE. The purpose of this fix is to allow the specific sequence of
changetype: modify delete: attrname - add: attrname attrname: somevalue -
Unfortunately, the way the DSE code works presents us with some quirks in the behavior: - There is an internal flag which keeps track of whether the value is the default value or not - Deleting an attribute resets the value to the default, but it will also delete the attribute from the internal DSE representation, which means if you attempt to delete an attribute which has already been deleted, the server will return No such attribute (16) because the attribute has already been deleted from the internal DSE - however, if you do an ldap search for the value, you will see it in the entry with the default value. - If the attribute gets in a weird state where it can't be deleted and it can't be added, a mod_replace will get it back to normal Platforms tested: RHEL6 x86_64 Flag Day: no Doc impact: no
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_config.c b/ldap/servers/slapd/back-ldbm/ldbm_config.c index d8f60b2..e265eaf 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_config.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_config.c @@ -1288,7 +1288,7 @@ void ldbm_config_setup_default(struct ldbminfo *li) char err_buf[SLAPI_DSE_RETURNTEXT_SIZE];
for (config = ldbm_config; config->config_name != NULL; config++) { - ldbm_config_set((void *)li, config->config_name, ldbm_config, NULL /* use default */, err_buf, CONFIG_PHASE_INITIALIZATION, 1 /* apply */); + ldbm_config_set((void *)li, config->config_name, ldbm_config, NULL /* use default */, err_buf, CONFIG_PHASE_INITIALIZATION, 1 /* apply */, LDAP_MOD_REPLACE); } }
@@ -1583,7 +1583,7 @@ int ldbm_config_ignored_attr(char *attr_name) }
/* Returns LDAP_SUCCESS on success */ -int ldbm_config_set(void *arg, char *attr_name, config_info *config_array, struct berval *bval, char *err_buf, int phase, int apply_mod) +int ldbm_config_set(void *arg, char *attr_name, config_info *config_array, struct berval *bval, char *err_buf, int phase, int apply_mod, int mod_op) { config_info *config; int use_default; @@ -1617,20 +1617,25 @@ int ldbm_config_set(void *arg, char *attr_name, config_info *config_array, struc return LDAP_UNWILLING_TO_PERFORM; }
- /* If the config phase is initialization or if bval is NULL, we will use - * the default value for the attribute. */ - if (CONFIG_PHASE_INITIALIZATION == phase || NULL == bval) { + /* If the config phase is initialization or if bval is NULL or if we are deleting + the value, we will use the default value for the attribute. */ + if ((CONFIG_PHASE_INITIALIZATION == phase) || (NULL == bval) || SLAPI_IS_MOD_DELETE(mod_op)) { if (CONFIG_FLAG_SKIP_DEFAULT_SETTING & config->config_flags) { return LDAP_SUCCESS; /* Skipping the default config setting */ } use_default = 1; } else { use_default = 0; - - /* Since we are setting the value for the config attribute, we - * need to turn on the CONFIG_FLAG_PREVIOUSLY_SET flag to make - * sure this attribute is shown. */ - config->config_flags |= CONFIG_FLAG_PREVIOUSLY_SET; + + /* cannot use mod add on a single valued attribute if the attribute was + previously set to a non-default value */ + if (SLAPI_IS_MOD_ADD(mod_op) && apply_mod && + (config->config_flags & CONFIG_FLAG_PREVIOUSLY_SET)) { + PR_snprintf(err_buf, SLAPI_DSE_RETURNTEXT_SIZE, + "cannot add a value to single valued attribute %s.\n", + attr_name); + return LDAP_OBJECT_CLASS_VIOLATION; + } }
switch(config->config_type) { @@ -1745,6 +1750,20 @@ int ldbm_config_set(void *arg, char *attr_name, config_info *config_array, struc retval = config->config_set_fn(arg, (void *) ((uintptr_t)int_val), err_buf, phase, apply_mod); break; } + + /* operation was successful and we applied the value? */ + if (!retval && apply_mod) { + /* Since we are setting the value for the config attribute, we + * need to turn on the CONFIG_FLAG_PREVIOUSLY_SET flag to make + * sure this attribute is shown. */ + if (use_default) { + /* attr deleted or we are using the default value */ + config->config_flags &= ~CONFIG_FLAG_PREVIOUSLY_SET; + } else { + /* attr set explicitly */ + config->config_flags |= CONFIG_FLAG_PREVIOUSLY_SET; + } + }
return retval; } @@ -1769,7 +1788,7 @@ static int parse_ldbm_config_entry(struct ldbminfo *li, Slapi_Entry *e, config_i slapi_attr_first_value(attr, &sval); bval = (struct berval *) slapi_value_get_berval(sval);
- if (ldbm_config_set(li, attr_name, config_array, bval, err_buf, CONFIG_PHASE_STARTUP, 1 /* apply */) != LDAP_SUCCESS) { + if (ldbm_config_set(li, attr_name, config_array, bval, err_buf, CONFIG_PHASE_STARTUP, 1 /* apply */, LDAP_MOD_REPLACE) != LDAP_SUCCESS) { LDAPDebug(LDAP_DEBUG_ANY, "Error with config attribute %s : %s\n", attr_name, err_buf, 0); return 1; } @@ -1811,21 +1830,19 @@ int ldbm_config_modify_entry_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore if (ldbm_config_ignored_attr(attr_name)) { continue; } - - if (SLAPI_IS_MOD_DELETE(mods[i]->mod_op) || - SLAPI_IS_MOD_ADD(mods[i]->mod_op)) { - rc= LDAP_UNWILLING_TO_PERFORM; - PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "%s attributes is not allowed", - (mods[i]->mod_op & LDAP_MOD_DELETE) ? "Deleting" : "Adding"); - } else if (mods[i]->mod_op & LDAP_MOD_REPLACE) { - /* This assumes there is only one bval for this mod. */ - rc = ldbm_config_set((void *) li, attr_name, ldbm_config, - ( mods[i]->mod_bvalues == NULL ) ? NULL - : mods[i]->mod_bvalues[0], returntext, - ((li->li_flags&LI_FORCE_MOD_CONFIG)? - CONFIG_PHASE_INTERNAL:CONFIG_PHASE_RUNNING), - apply_mod); - } + + /* when deleting a value, and this is the last or only value, set + the config param to its default value + when adding a value, if the value is set to its default value, replace + it with the new value - otherwise, if it is single valued, reject the + operation with TYPE_OR_VALUE_EXISTS */ + /* This assumes there is only one bval for this mod. */ + rc = ldbm_config_set((void *) li, attr_name, ldbm_config, + ( mods[i]->mod_bvalues == NULL ) ? NULL + : mods[i]->mod_bvalues[0], returntext, + ((li->li_flags&LI_FORCE_MOD_CONFIG)? + CONFIG_PHASE_INTERNAL:CONFIG_PHASE_RUNNING), + apply_mod, mods[i]->mod_op); } }
@@ -1853,7 +1870,8 @@ void ldbm_config_internal_set(struct ldbminfo *li, char *attrname, char *value) bval.bv_len = strlen(value);
if (ldbm_config_set((void *) li, attrname, ldbm_config, &bval, - err_buf, CONFIG_PHASE_INTERNAL, 1 /* apply */) != LDAP_SUCCESS) { + err_buf, CONFIG_PHASE_INTERNAL, 1 /* apply */, + LDAP_MOD_REPLACE) != LDAP_SUCCESS) { LDAPDebug(LDAP_DEBUG_ANY, "Internal Error: Error setting instance config attr %s to %s: %s\n", attrname, value, err_buf); diff --git a/ldap/servers/slapd/back-ldbm/ldbm_config.h b/ldap/servers/slapd/back-ldbm/ldbm_config.h index 5ba52a6..ffbc39f 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_config.h +++ b/ldap/servers/slapd/back-ldbm/ldbm_config.h @@ -163,7 +163,7 @@ struct config_info { int ldbm_config_add_dse_entries(struct ldbminfo *li, char **entries, char *string1, char *string2, char *string3, int flags); int ldbm_config_add_dse_entry(struct ldbminfo *li, char *entry, int flags); void ldbm_config_get(void *arg, config_info *config, char *buf); -int ldbm_config_set(void *arg, char *attr_name, config_info *config_array, struct berval *bval, char *err_buf, int phase, int apply_mod); +int ldbm_config_set(void *arg, char *attr_name, config_info *config_array, struct berval *bval, char *err_buf, int phase, int apply_mod, int mod_op); int ldbm_config_ignored_attr(char *attr_name);
/* Functions in ldbm_instance_config.c used in ldbm_config.c */ diff --git a/ldap/servers/slapd/back-ldbm/ldbm_instance_config.c b/ldap/servers/slapd/back-ldbm/ldbm_instance_config.c index 882f10a..7709cfb 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_instance_config.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_instance_config.c @@ -303,7 +303,7 @@ ldbm_instance_config_setup_default(ldbm_instance *inst) char err_buf[BUFSIZ];
for (config = ldbm_instance_config; config->config_name != NULL; config++) { - ldbm_config_set((void *)inst, config->config_name, ldbm_instance_config, NULL /* use default */, err_buf, CONFIG_PHASE_INITIALIZATION, 1 /* apply */); + ldbm_config_set((void *)inst, config->config_name, ldbm_instance_config, NULL /* use default */, err_buf, CONFIG_PHASE_INITIALIZATION, 1 /* apply */, LDAP_MOD_REPLACE); } }
@@ -462,7 +462,7 @@ parse_ldbm_instance_config_entry(ldbm_instance *inst, Slapi_Entry *e, config_inf bval = (struct berval *) slapi_value_get_berval(sval);
if (ldbm_config_set((void *) inst, attr_name, config_array, bval, - err_buf, CONFIG_PHASE_STARTUP, 1 /* apply */) != LDAP_SUCCESS) { + err_buf, CONFIG_PHASE_STARTUP, 1 /* apply */, LDAP_MOD_REPLACE) != LDAP_SUCCESS) { LDAPDebug(LDAP_DEBUG_ANY, "Error with config attribute %s : %s\n", attr_name, err_buf, 0); return 1; @@ -788,18 +788,10 @@ ldbm_instance_modify_config_entry_callback(Slapi_PBlock *pb, Slapi_Entry* entryB continue; }
- if ((mods[i]->mod_op & LDAP_MOD_DELETE) || - (mods[i]->mod_op & LDAP_MOD_ADD)) { - rc= LDAP_UNWILLING_TO_PERFORM; - PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "%s attributes is not allowed", - (mods[i]->mod_op & LDAP_MOD_DELETE) ? - "Deleting" : "Adding"); - } else if (mods[i]->mod_op & LDAP_MOD_REPLACE) { /* This assumes there is only one bval for this mod. */ - rc = ldbm_config_set((void *) inst, attr_name, - ldbm_instance_config, mods[i]->mod_bvalues[0], returntext, - CONFIG_PHASE_RUNNING, apply_mod); - } + rc = ldbm_config_set((void *) inst, attr_name, + ldbm_instance_config, mods[i]->mod_bvalues[0], returntext, + CONFIG_PHASE_RUNNING, apply_mod, mods[i]->mod_op); } }
@@ -827,7 +819,7 @@ ldbm_instance_config_internal_set(ldbm_instance *inst, char *attrname, char *val bval.bv_len = strlen(value);
if (ldbm_config_set((void *) inst, attrname, ldbm_instance_config, &bval, - err_buf, CONFIG_PHASE_INTERNAL, 1 /* apply */) != LDAP_SUCCESS) { + err_buf, CONFIG_PHASE_INTERNAL, 1 /* apply */, LDAP_MOD_REPLACE) != LDAP_SUCCESS) { LDAPDebug(LDAP_DEBUG_ANY, "Internal Error: Error setting instance config attr %s to %s: %s\n", attrname, value, err_buf);
389-commits@lists.fedoraproject.org