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(a)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(a)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);