https://bugs.openldap.org/show_bug.cgi?id=8174
--- Comment #4 from Vladimir Cunat <vladimir.cunat(a)nic.cz> ---
FYI, blocking the transaction after mdb_drop isn't great. Some projects got
caught by that: postfix, knot-dns, knot-resolver (I didn't search specifically,
so maybe more).
Personally I find it useful to clear the whole DB and fill new contents, all
within a single RW transaction (so that noone sees the WIP state during that
rewrite). But I guess everyone will have to try to find some workarounds
now...
--
You are receiving this mail because:
You are on the CC list for the issue.
https://bugs.openldap.org/show_bug.cgi?id=10534
Issue ID: 10534
Summary: mdb_env_get_maxkeysize(): requires an _env_open()ed
handle
Product: LMDB
Version: unspecified
Hardware: All
OS: All
Status: UNCONFIRMED
Keywords: needs_review
Severity: normal
Priority: ---
Component: liblmdb
Assignee: bugs(a)openldap.org
Reporter: steffen(a)sdaoden.eu
Target Milestone: ---
Created attachment 1174
--> https://bugs.openldap.org/attachment.cgi?id=1174&action=edit
git-enabled patch
Super minor, but my LMDB implementation for the bogofilter program was buggy
because of this. They had to fix it accordingly after almost 8 years, when
updating to LMDB 1.0.
Suggested fix would be something like
- * @param[in] env An environment handle returned by #mdb_env_create()
+ * @param[in] env An environment handle that is #mdb_env_open()
Thanks! And ciao.
--
You are receiving this mail because:
You are on the CC list for the issue.
https://bugs.openldap.org/show_bug.cgi?id=10529
Issue ID: 10529
Summary: assertion failure
Product: LMDB
Version: 1.0.0
Hardware: x86_64
OS: Linux
Status: UNCONFIRMED
Keywords: needs_review
Severity: normal
Priority: ---
Component: liblmdb
Assignee: bugs(a)openldap.org
Reporter: christopher(a)gmerlin.de
Target Milestone: ---
When testing the OCaml bindings with lmdb 1.0 I encountered this assertion
failure:
at src/mdb.c:7588: Assertion 'root > 1' failed in mdb_page_search()")
It was triggered by:
- start transaction
- add new key-value
- commit transaction
- rollback transaction
- start read only transaction
- try to get any key -> assertion failure
On another note I notice that this fails with MDB_CANT_ROLLBACK:
- start transaction
- commit ¡EMPTY! transaction
- rollback transaction -> MDB_CANT_ROLLBACK
Of course this is a nonsensical transaction. But nevertheless maybe this case
should be mentioned in the documentation, too.
--
You are receiving this mail because:
You are on the CC list for the issue.
https://bugs.openldap.org/show_bug.cgi?id=10528
Issue ID: 10528
Summary: core.ldif fails to load via "include:" in cn=config on
Symas OpenLDAP 2.6.13-3 (RHEL 9)
Product: OpenLDAP
Version: 2.6.13
Hardware: x86_64
OS: Linux
Status: UNCONFIRMED
Keywords: needs_review
Severity: normal
Priority: ---
Component: slapd
Assignee: bugs(a)openldap.org
Reporter: lucas.vicente(a)ebz.tec.br
Target Milestone: ---
Hello,
We are experiencing an issue while trying to load the core.ldif schema default
using the dynamic configuration (cn=config).
When using the following in my LDIF:
include: file:///opt/symas/etc/openldap/schema/core.ldif
I get this error:
olcAttributeTypes: value #48 olcAttributeTypes: Unexpected token before MUST c
MAY ( searchGuide $ description ) )
slapadd: could not add entry dn="cn={0}core,cn=schema,cn=config" (line=14):
olcAttributeTypes: Unexpected token before MUST c MAY ( searchGuide $
description ) )
Obs:
If I create a slapd.conf that includes the core schema and run:
slaptest -f slapd.conf -F /tmp/slapd.d
It works without errors. However, when trying to load the same schema using
slapadd + include: in cn=config, it fails.
For reference, I tested the same steps on version 2.6.10 and it worked without
errors.
Steps to reproduce:
Install Symas OpenLDAP 2.6.13 on RHEL 9
Try to load the core schema using:
dn: cn=schema,cn=config
objectClass: olcSchemaConfig
cn: schema
include: file:///opt/symas/etc/openldap/schema/core.ldif
Would you be able to verify this behavior?
Thanks!
--
You are receiving this mail because:
You are on the CC list for the issue.
https://bugs.openldap.org/show_bug.cgi?id=10526
Issue ID: 10526
Summary: back-mdb: mdb_idl_intersection is O(ID-gap), not O(n),
when a short candidate list is ANDed with a range
Product: OpenLDAP
Version: 2.5.20
Hardware: All
OS: Linux
Status: UNCONFIRMED
Keywords: needs_review
Severity: normal
Priority: ---
Component: backends
Assignee: bugs(a)openldap.org
Reporter: choeger(a)open-xchange.com
Target Milestone: ---
Created attachment 1157
--> https://bugs.openldap.org/attachment.cgi?id=1157&action=edit
the patch above
----------------------------------------------------------------------------
Note
The below report including the patch has been generated by Claude Opus 4.8.
I built packages based on the OpenLDAP-LTB project version v2.5.20 and verified
in our problematic production deployment.
This refers to the following thread:
https://lists.openldap.org/hyperkitty/list/openldap-technical@openldap.org/…
End Note
----------------------------------------------------------------------------
SUMMARY
-------
AND-filter searches can be orders of magnitude slower than the size of their
result set warrants. mdb_idl_intersection() falls back to a generic
element-at-a-time merge whose cost is proportional to the distance in ID space
between candidate IDs, not to the number of candidates. When one operand is a
range (any indexed term matching more than the IDL range threshold, e.g. a
common objectClass) and the other is a short list of IDs that are widely
separated, the merge walks the range one ID at a time across the entire gap.
This is common in practice: filters of the form
(&(objectClass=X)(someAttr=val)...) hit it whenever someAttr matches a small
number of entries whose IDs happen to be far apart and objectClass=X is stored
as a range that does not fully cover that span.
ENVIRONMENT
-----------
- OpenLDAP 2.5.19, slapd back-mdb.
- ~4.6M entries. An attribute is indexed eq and a given value normally matches
exactly one entry. A common objectClass value matches ~2,000,000 entries and
is therefore stored as an IDL range (it exceeds MDB_idl_db_max; see
servers/slapd/back-mdb/idl.c:467, "No room, convert to a range").
SYMPTOM
-------
Query: (&(objectClass=<common>)(<almost-unique-attr>=<value>)(<attr>=*))
The filter resolves to a single entry in all cases.
- When <almost-unique-attr>=<value> matches ONE entry: the search is very fast.
- When it matches TWO entries whose IDs are far apart (here 1759457 and
2731413, a gap of ~972,000), the same search becomes roughly 20x slower,
even though the AND still yields a single entry.
perf shows nearly all CPU in mdb_idl_next() and mdb_idl_intersection().
Enabling LDAP_DEBUG_FILTER and inspecting the per-term candidate counts
confirms the broad term is a range; gdb in mdb_idl_intersection shows
idmin/idmax equal to the two widely separated IDs.
Neither index_hash64 nor dropping the substring index changes the timing;
the cost is not in the index key lookups, it is in the candidate intersection.
ROOT CAUSE
----------
In servers/slapd/back-mdb/idl.c, mdb_idl_intersection() has fast paths for
both-ranges, for idmin==idmax, and for "range fully covers list". Anything
that misses those falls into a generic merge:
cursora = cursorb = idmin;
ida = mdb_idl_first( a, &cursora );
idb = mdb_idl_first( b, &cursorb );
cursorc = 0;
while( ida <= idmax || idb <= idmax ) {
if( ida == idb ) {
a[++cursorc] = ida;
ida = mdb_idl_next( a, &cursora );
idb = mdb_idl_next( b, &cursorb );
} else if ( ida < idb ) {
ida = mdb_idl_next( a, &cursora );
} else {
idb = mdb_idl_next( b, &cursorb );
}
}
For a range, mdb_idl_next() returns ++(*cursor), i.e. consecutive integers.
So when b is a range that does not fully cover list a (the "range fully covers
list" shortcut is missed because the non-matching list member lies outside the
range bounds), the loop advances idb one integer at a time from idmin to idmax.
With the two matches ~972,000 apart, that is ~972,000 iterations per search.
The single-match case is fast only because it lands on the idmin==idmax or
"range fully covers list" shortcut; it has nothing to do with the index.
The same loop is also O(gap) for the list-vs-list case (a populous list ANDed
with a short, widely-spread list): it walks the populous list across the gap.
mdb_idl_intersection() is reached for every non-first term of an AND filter via
list_candidates() in servers/slapd/back-mdb/filterindex.c.
REPRODUCTION (without specific data)
------------------------------------
1. Load a DB where some indexed attribute value V matches more than
MDB_idl_db_max entries (so V is stored as a range), and where the range's
[lo,hi] does not span the whole DB.
2. Pick another indexed attribute A and two entries that share a value W on A,
such that one of them is NOT in V's range and their IDs are far apart.
3. Time (&(A=W)) vs (&(V)(A=W)) repeatedly. The second is dramatically slower
despite returning fewer (or equal) entries.
A standalone harness that extracts the real 2.5.19 IDL routines, cross-checks a
fixed mdb_idl_intersection against brute-force set intersection, and benchmarks
the pathology is attached (idl_intersection_test.c).
PROPOSED FIX
------------
mdb_idl_intersection() never needs to iterate a range. After the existing
"range fully covers list" shortcut:
- If b is a range, the result is just the members of list a that fall within
[first,last]: iterate the (bounded) list, test each against the bounds.
O(|a|) instead of O(range width).
- If both a and b are lists, keep the sorted merge but, when the cursors
diverge, binary-search (mdb_idl_search) the lagging list forward to the
other's current value rather than stepping one element at a time. Each
catch-up becomes O(log n) instead of O(gap).
Result ordering (ascending) and the a[0] count convention are preserved, as is
the swap/copy-back behaviour. The in-place writes are safe: the write index
(cursorc, number of matches) never exceeds the read index.
Patch against OPENLDAP_REL_ENG_2_5_19 (applies cleanly to RE25 and master HEAD
as well); also attached as mdb-idl-intersection.patch:
--- a/servers/slapd/back-mdb/idl.c
+++ b/servers/slapd/back-mdb/idl.c
@@ -759,23 +759,49 @@
goto done;
}
- /* Fine, do the intersection one element at a time.
- * First advance to idmin in both IDLs.
+ /* If b is a range (and does not fully cover a, handled above), the
+ * intersection is just the elements of list a that fall within the
+ * range bounds. Walk the (bounded) list, never the (potentially huge)
+ * range: O(|a|), not O(range width).
*/
- cursora = cursorb = idmin;
- ida = mdb_idl_first( a, &cursora );
- idb = mdb_idl_first( b, &cursorb );
- cursorc = 0;
+ if ( MDB_IDL_IS_RANGE( b ) ) {
+ ID lo = MDB_IDL_RANGE_FIRST( b );
+ ID hi = MDB_IDL_RANGE_LAST( b );
+ cursorc = 0;
+ for ( ida = mdb_idl_first( a, &cursora );
+ ida != NOID;
+ ida = mdb_idl_next( a, &cursora ) ) {
+ if ( ida < lo )
+ continue;
+ if ( ida > hi )
+ break;
+ a[++cursorc] = ida;
+ }
+ a[0] = cursorc;
+ goto done;
+ }
- while( ida <= idmax || idb <= idmax ) {
- if( ida == idb ) {
+ /* Both a and b are lists. Sorted-merge intersection, but when the two
+ * cursors diverge, binary-search the lagging list forward to the
other's
+ * current value instead of stepping one element at a time. This keeps
a
+ * large gap in one list (e.g. two widely separated matches intersected
+ * against a populous list) from forcing a linear scan of the other
list
+ * across the whole gap: each catch-up is O(log n) rather than O(gap).
+ */
+ cursora = mdb_idl_search( a, idmin );
+ cursorb = mdb_idl_search( b, idmin );
+ cursorc = 0;
+ while ( cursora <= a[0] && cursorb <= b[0] ) {
+ ida = a[cursora];
+ idb = b[cursorb];
+ if ( ida == idb ) {
a[++cursorc] = ida;
- ida = mdb_idl_next( a, &cursora );
- idb = mdb_idl_next( b, &cursorb );
+ cursora++;
+ cursorb++;
} else if ( ida < idb ) {
- ida = mdb_idl_next( a, &cursora );
+ cursora = mdb_idl_search( a, idb );
} else {
- idb = mdb_idl_next( b, &cursorb );
+ cursorb = mdb_idl_search( b, ida );
}
}
a[0] = cursorc;
TESTING
-------
Using the attached harness (the patched function is byte-for-byte the shipped
code):
- Correctness: 400,000 randomized trials (two seeds) over zero/list/range
operands of varied sizes and gaps, in both argument orders, cross-checked
against brute-force set intersection. Zero mismatches.
- The reported case, list {1759457, 2731413} intersected with a 2,000,000-entry
range [1 .. 2731412] that does not cover the upper member, 1200 iterations:
original: 2.54 s, 1,166,348,400 mdb_idl_next calls, result count = 1
fixed: ~0 s, 1,200 mdb_idl_next calls, result count = 1
- Single-value baseline (original): ~0 s, 0 mdb_idl_next calls, confirming the
original is fast only for the single-match case.
--
You are receiving this mail because:
You are on the CC list for the issue.
https://bugs.openldap.org/show_bug.cgi?id=8803
Quanah Gibson-Mount <quanah(a)openldap.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Resolution|TEST |FIXED
--
You are receiving this mail because:
You are on the CC list for the issue.
https://bugs.openldap.org/show_bug.cgi?id=9223
Bug ID: 9223
Summary: Add support for incremental backup
Product: LMDB
Version: unspecified
Hardware: All
OS: All
Status: UNCONFIRMED
Severity: normal
Priority: ---
Component: liblmdb
Assignee: bugs(a)openldap.org
Reporter: quanah(a)openldap.org
Target Milestone: ---
For LMDB 1.0, add support for incremental backups
--
You are receiving this mail because:
You are on the CC list for the bug.
https://bugs.openldap.org/show_bug.cgi?id=9027
Quanah Gibson-Mount <quanah(a)openldap.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Resolution|TEST |FIXED
--
You are receiving this mail because:
You are on the CC list for the issue.
https://bugs.openldap.org/show_bug.cgi?id=8704
Quanah Gibson-Mount <quanah(a)openldap.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Resolution|TEST |FIXED
--
You are receiving this mail because:
You are on the CC list for the issue.
https://bugs.openldap.org/show_bug.cgi?id=8209
Quanah Gibson-Mount <quanah(a)openldap.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Resolution|TEST |FIXED
--
You are receiving this mail because:
You are on the CC list for the issue.