1 /* filterindex.c - generate the list of candidate entries from a filter */
4 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
11 #include <ac/string.h>
16 static int presence_candidates(
18 AttributeDescription *desc,
21 static int equality_candidates(
23 AttributeAssertion *ava,
26 static int approx_candidates(
28 AttributeAssertion *ava,
31 static int substring_candidates(
33 SubstringsAssertion *sub,
37 static int list_candidates(
46 bdb_filter_candidates(
55 LDAP_LOG ( INDEX, ENTRY, "=> bdb_filter_candidates\n", 0, 0, 0 );
57 Debug( LDAP_DEBUG_FILTER, "=> bdb_filter_candidates\n", 0, 0, 0 );
60 switch ( f->f_choice ) {
61 case SLAPD_FILTER_COMPUTED:
64 case SLAPD_FILTER_DN_ONE:
66 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tDN ONE\n", 0, 0, 0 );
68 Debug( LDAP_DEBUG_FILTER, "\tDN ONE\n", 0, 0, 0 );
70 rc = bdb_dn2idl( op->o_bd, f->f_dn, DN_ONE_PREFIX, ids );
71 if( rc == DB_NOTFOUND ) {
77 case SLAPD_FILTER_DN_SUBTREE:
79 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tDN SUBTREE\n", 0, 0, 0 );
81 Debug( LDAP_DEBUG_FILTER, "\tDN SUBTREE\n", 0, 0, 0 );
83 rc = bdb_dn2idl( op->o_bd, f->f_dn, DN_SUBTREE_PREFIX, ids );
86 case LDAP_FILTER_PRESENT:
88 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tPRESENT\n", 0, 0, 0 );
90 Debug( LDAP_DEBUG_FILTER, "\tPRESENT\n", 0, 0, 0 );
92 rc = presence_candidates( op, f->f_desc, ids );
95 case LDAP_FILTER_EQUALITY:
97 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tEQUALITY\n", 0, 0, 0 );
99 Debug( LDAP_DEBUG_FILTER, "\tEQUALITY\n", 0, 0, 0 );
101 rc = equality_candidates( op, f->f_ava, ids, tmp );
104 case LDAP_FILTER_APPROX:
106 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tAPPROX\n", 0, 0, 0 );
108 Debug( LDAP_DEBUG_FILTER, "\tAPPROX\n", 0, 0, 0 );
110 rc = approx_candidates( op, f->f_ava, ids, tmp );
113 case LDAP_FILTER_SUBSTRINGS:
115 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tSUBSTRINGS\n", 0, 0, 0 );
117 Debug( LDAP_DEBUG_FILTER, "\tSUBSTRINGS\n", 0, 0, 0 );
119 rc = substring_candidates( op, f->f_sub, ids, tmp );
123 /* no GE index, use pres */
125 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tGE\n", 0, 0, 0 );
127 Debug( LDAP_DEBUG_FILTER, "\tGE\n", 0, 0, 0 );
129 rc = presence_candidates( op, f->f_ava->aa_desc, ids );
133 /* no LE index, use pres */
135 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tLE\n", 0, 0, 0 );
137 Debug( LDAP_DEBUG_FILTER, "\tLE\n", 0, 0, 0 );
139 rc = presence_candidates( op, f->f_ava->aa_desc, ids );
142 case LDAP_FILTER_NOT:
143 /* no indexing to support NOT filters */
145 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tNOT\n",0, 0, 0 );
147 Debug( LDAP_DEBUG_FILTER, "\tNOT\n", 0, 0, 0 );
149 { struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
150 BDB_IDL_ALL( bdb, ids );
154 case LDAP_FILTER_AND:
156 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tAND\n", 0, 0, 0 );
158 Debug( LDAP_DEBUG_FILTER, "\tAND\n", 0, 0, 0 );
160 rc = list_candidates( op,
161 f->f_and, LDAP_FILTER_AND, ids, tmp, stack );
166 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tOR\n", 0, 0, 0 );
168 Debug( LDAP_DEBUG_FILTER, "\tOR\n", 0, 0, 0 );
170 rc = list_candidates( op,
171 f->f_or, LDAP_FILTER_OR, ids, tmp, stack );
176 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tUNKNOWN\n", 0, 0, 0 );
178 Debug( LDAP_DEBUG_FILTER, "\tUNKNOWN %lu\n",
179 (unsigned long) f->f_choice, 0, 0 );
184 LDAP_LOG ( INDEX, RESULTS,
185 "<= bdb_filter_candidates: id=%ld first=%ld last=%ld\n",
186 (long)ids[0], (long)BDB_IDL_FIRST( ids ), (long) BDB_IDL_LAST( ids ));
188 Debug( LDAP_DEBUG_FILTER,
189 "<= bdb_filter_candidates: id=%ld first=%ld last=%ld\n",
191 (long) BDB_IDL_FIRST( ids ),
192 (long) BDB_IDL_LAST( ids ) );
207 struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
212 LDAP_LOG ( INDEX, ARGS, "=> bdb_list_candidates: 0x%x\n", ftype, 0 , 0 );
214 Debug( LDAP_DEBUG_FILTER, "=> bdb_list_candidates 0x%x\n", ftype, 0, 0 );
217 /* Copy so we can propagate pre-computed IDLs */
218 BDB_IDL_CPY( save, ids );
220 for ( f = flist; f != NULL; f = f->f_next ) {
221 rc = bdb_filter_candidates( op, f, save, tmp,
222 save+BDB_IDL_UM_SIZE );
225 if ( ftype == LDAP_FILTER_AND ) {
233 if ( ftype == LDAP_FILTER_AND ) {
235 BDB_IDL_CPY( ids, save );
237 bdb_idl_intersection( ids, save );
239 if( BDB_IDL_IS_ZERO( ids ) )
243 BDB_IDL_CPY( ids, save );
245 bdb_idl_union( ids, save );
250 if( rc == LDAP_SUCCESS ) {
252 LDAP_LOG ( INDEX, RESULTS,
253 "<= bdb_list_candidates: id=%ld first=%ld last=%ld\n",
254 (long) ids[0], (long) BDB_IDL_FIRST( ids ),
255 (long) BDB_IDL_LAST( ids ) );
257 Debug( LDAP_DEBUG_FILTER,
258 "<= bdb_list_candidates: id=%ld first=%ld last=%ld\n",
260 (long) BDB_IDL_FIRST(ids),
261 (long) BDB_IDL_LAST(ids) );
266 LDAP_LOG ( INDEX, ARGS, "<= bdb_list_candidates: rc=%d\n", rc, 0, 0 );
268 Debug( LDAP_DEBUG_FILTER,
269 "<= bdb_list_candidates: undefined rc=%d\n",
280 AttributeDescription *desc,
283 struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
287 struct berval prefix = {0, NULL};
290 LDAP_LOG ( INDEX, ENTRY, "=> bdb_presence_candidates (%s)\n",
291 desc->ad_cname.bv_val, 0, 0 );
293 Debug( LDAP_DEBUG_TRACE, "=> bdb_presence_candidates (%s)\n",
294 desc->ad_cname.bv_val, 0, 0 );
297 if( desc == slap_schema.si_ad_objectClass ) {
298 BDB_IDL_ALL( bdb, ids );
302 rc = bdb_index_param( op->o_bd, desc, LDAP_FILTER_PRESENT,
303 &db, &mask, &prefix );
305 if( rc != LDAP_SUCCESS ) {
307 LDAP_LOG ( INDEX, RESULTS,
308 "<= bdb_presence_candidates: (%s) index_param "
310 desc->ad_cname.bv_val, rc, 0 );
312 Debug( LDAP_DEBUG_TRACE,
313 "<= bdb_presence_candidates: (%s) index_param "
315 desc->ad_cname.bv_val, rc, 0 );
323 LDAP_LOG(INDEX, RESULTS,
324 "<= bdb_presence_candidates: (%s) not indexed\n",
325 desc->ad_cname.bv_val, 0, 0 );
327 Debug( LDAP_DEBUG_TRACE,
328 "<= bdb_presence_candidates: (%s) not indexed\n",
329 desc->ad_cname.bv_val, 0, 0 );
334 if( prefix.bv_val == NULL ) {
336 LDAP_LOG(INDEX, RESULTS,
337 "<= bdb_presence_candidates: (%s) no prefix\n",
338 desc->ad_cname.bv_val, 0, 0 );
340 Debug( LDAP_DEBUG_TRACE,
341 "<= bdb_presence_candidates: (%s) no prefix\n",
342 desc->ad_cname.bv_val, 0, 0 );
347 rc = bdb_key_read( op->o_bd, db, NULL, &prefix, ids );
349 if( rc == DB_NOTFOUND ) {
352 } else if( rc != LDAP_SUCCESS ) {
354 LDAP_LOG ( INDEX, RESULTS,
355 "<= bdb_presence_candidates: (%s) "
356 "key read failed (%d)\n",
357 desc->ad_cname.bv_val, rc, 0 );
359 Debug( LDAP_DEBUG_TRACE,
360 "<= bdb_presense_candidates: (%s) "
361 "key read failed (%d)\n",
362 desc->ad_cname.bv_val, rc, 0 );
368 LDAP_LOG ( INDEX, RESULTS,
369 "<= bdb_presence_candidates: id=%ld first=%ld last=%ld\n",
370 (long)ids[0], (long)BDB_IDL_FIRST( ids ), (long)BDB_IDL_LAST( ids ) );
372 Debug(LDAP_DEBUG_TRACE,
373 "<= bdb_presence_candidates: id=%ld first=%ld last=%ld\n",
375 (long) BDB_IDL_FIRST(ids),
376 (long) BDB_IDL_LAST(ids) );
386 AttributeAssertion *ava,
394 struct berval prefix = {0, NULL};
395 struct berval *keys = NULL;
399 LDAP_LOG ( INDEX, ENTRY, "=> bdb_equality_candidates (%s)\n",
400 ava->aa_desc->ad_cname.bv_val, 0, 0 );
402 Debug( LDAP_DEBUG_TRACE, "=> bdb_equality_candidates (%s)\n",
403 ava->aa_desc->ad_cname.bv_val, 0, 0 );
406 rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_EQUALITY,
407 &db, &mask, &prefix );
409 if( rc != LDAP_SUCCESS ) {
411 LDAP_LOG ( INDEX, RESULTS,
412 "<= bdb_equality_candidates: (%s) "
413 "index_param failed (%d)\n",
414 ava->aa_desc->ad_cname.bv_val, rc, 0);
416 Debug( LDAP_DEBUG_ANY,
417 "<= bdb_equality_candidates: (%s) "
418 "index_param failed (%d)\n",
419 ava->aa_desc->ad_cname.bv_val, rc, 0 );
426 LDAP_LOG(INDEX, RESULTS,
427 "<= bdb_equality_candidates: (%s) not indexed\n",
428 ava->aa_desc->ad_cname.bv_val, 0, 0 );
430 Debug( LDAP_DEBUG_ANY,
431 "<= bdb_equality_candidates: (%s) not indexed\n",
432 ava->aa_desc->ad_cname.bv_val, 0, 0 );
437 mr = ava->aa_desc->ad_type->sat_equality;
442 if( !mr->smr_filter ) {
446 rc = (mr->smr_filter)(
447 LDAP_FILTER_EQUALITY,
449 ava->aa_desc->ad_type->sat_syntax,
453 &keys, op->o_tmpmemctx );
455 if( rc != LDAP_SUCCESS ) {
457 LDAP_LOG ( INDEX, RESULTS,
458 "<= bdb_equality_candidates: (%s, %s) "
459 "MR filter failed (%d)\n",
460 prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
462 Debug( LDAP_DEBUG_TRACE,
463 "<= bdb_equality_candidates: (%s, %s) "
464 "MR filter failed (%d)\n",
465 prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
472 LDAP_LOG ( INDEX, RESULTS,
473 "<= bdb_equality_candidates: (%s) no keys\n",
474 ava->aa_desc->ad_cname.bv_val, 0, 0 );
476 Debug( LDAP_DEBUG_TRACE,
477 "<= bdb_equality_candidates: (%s) no keys\n",
478 ava->aa_desc->ad_cname.bv_val, 0, 0 );
483 for ( i= 0; keys[i].bv_val != NULL; i++ ) {
484 rc = bdb_key_read( op->o_bd, db, NULL, &keys[i], tmp );
486 if( rc == DB_NOTFOUND ) {
489 } else if( rc != LDAP_SUCCESS ) {
491 LDAP_LOG ( INDEX, RESULTS,
492 "<= bdb_equality_candidates: (%s) "
493 "key read failed (%d)\n",
494 ava->aa_desc->ad_cname.bv_val, rc, 0 );
496 Debug( LDAP_DEBUG_TRACE,
497 "<= bdb_equality_candidates: (%s) "
498 "key read failed (%d)\n",
499 ava->aa_desc->ad_cname.bv_val, rc, 0 );
504 if( BDB_IDL_IS_ZERO( tmp ) ) {
506 LDAP_LOG ( INDEX, RESULTS,
507 "<= bdb_equality_candidates: (%s) NULL\n",
508 ava->aa_desc->ad_cname.bv_val, 0, 0);
510 Debug( LDAP_DEBUG_TRACE,
511 "<= bdb_equality_candidates: (%s) NULL\n",
512 ava->aa_desc->ad_cname.bv_val, 0, 0 );
519 BDB_IDL_CPY( ids, tmp );
521 bdb_idl_intersection( ids, tmp );
524 if( BDB_IDL_IS_ZERO( ids ) )
528 ber_bvarray_free_x( keys, op->o_tmpmemctx );
531 LDAP_LOG ( INDEX, RESULTS,
532 "<= bdb_equality_candidates: id=%ld first=%ld last=%ld\n",
533 (long) ids[0], (long) BDB_IDL_FIRST( ids ),
534 (long) BDB_IDL_LAST( ids ) );
536 Debug( LDAP_DEBUG_TRACE,
537 "<= bdb_equality_candidates: id=%ld, first=%ld, last=%ld\n",
539 (long) BDB_IDL_FIRST(ids),
540 (long) BDB_IDL_LAST(ids) );
549 AttributeAssertion *ava,
557 struct berval prefix = {0, NULL};
558 struct berval *keys = NULL;
562 LDAP_LOG ( INDEX, ENTRY, "=> bdb_approx_candidates (%s)\n",
563 ava->aa_desc->ad_cname.bv_val, 0, 0 );
565 Debug( LDAP_DEBUG_TRACE, "=> bdb_approx_candidates (%s)\n",
566 ava->aa_desc->ad_cname.bv_val, 0, 0 );
569 rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_APPROX,
570 &db, &mask, &prefix );
572 if( rc != LDAP_SUCCESS ) {
574 LDAP_LOG ( INDEX, RESULTS,
575 "<= bdb_approx_candidates: (%s) "
576 "index_param failed (%d)\n",
577 ava->aa_desc->ad_cname.bv_val, rc, 0 );
579 Debug( LDAP_DEBUG_ANY,
580 "<= bdb_approx_candidates: (%s) "
581 "index_param failed (%d)\n",
582 ava->aa_desc->ad_cname.bv_val, rc, 0 );
589 LDAP_LOG(INDEX, RESULTS,
590 "<= bdb_approx_candidates: (%s) not indexed\n",
591 ava->aa_desc->ad_cname.bv_val, 0, 0 );
593 Debug( LDAP_DEBUG_ANY,
594 "<= bdb_approx_candidates: (%s) not indexed\n",
595 ava->aa_desc->ad_cname.bv_val, 0, 0 );
600 mr = ava->aa_desc->ad_type->sat_approx;
602 /* no approx matching rule, try equality matching rule */
603 mr = ava->aa_desc->ad_type->sat_equality;
610 if( !mr->smr_filter ) {
614 rc = (mr->smr_filter)(
617 ava->aa_desc->ad_type->sat_syntax,
621 &keys, op->o_tmpmemctx );
623 if( rc != LDAP_SUCCESS ) {
625 LDAP_LOG ( INDEX, RESULTS,
626 "<= bdb_approx_candidates: (%s, %s) "
627 "MR filter failed (%d)\n",
628 prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
630 Debug( LDAP_DEBUG_TRACE,
631 "<= bdb_approx_candidates: (%s, %s) "
632 "MR filter failed (%d)\n",
633 prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
640 LDAP_LOG ( INDEX, RESULTS,
641 "<= bdb_approx_candidates: (%s) no keys (%s)\n",
642 prefix.bv_val, ava->aa_desc->ad_cname.bv_val, 0 );
644 Debug( LDAP_DEBUG_TRACE,
645 "<= bdb_approx_candidates: (%s) no keys (%s)\n",
646 prefix.bv_val, ava->aa_desc->ad_cname.bv_val, 0 );
651 for ( i= 0; keys[i].bv_val != NULL; i++ ) {
652 rc = bdb_key_read( op->o_bd, db, NULL, &keys[i], tmp );
654 if( rc == DB_NOTFOUND ) {
658 } else if( rc != LDAP_SUCCESS ) {
660 LDAP_LOG ( INDEX, RESULTS,
661 "<= bdb_approx_candidates: (%s) "
662 "key read failed (%d)\n",
663 ava->aa_desc->ad_cname.bv_val, rc, 0);
665 Debug( LDAP_DEBUG_TRACE,
666 "<= bdb_approx_candidates: (%s) "
667 "key read failed (%d)\n",
668 ava->aa_desc->ad_cname.bv_val, rc, 0 );
673 if( BDB_IDL_IS_ZERO( tmp ) ) {
675 LDAP_LOG ( INDEX, RESULTS,
676 "<= bdb_approx_candidates: (%s) NULL\n",
677 ava->aa_desc->ad_cname.bv_val, 0, 0 );
679 Debug( LDAP_DEBUG_TRACE,
680 "<= bdb_approx_candidates: (%s) NULL\n",
681 ava->aa_desc->ad_cname.bv_val, 0, 0 );
688 BDB_IDL_CPY( ids, tmp );
690 bdb_idl_intersection( ids, tmp );
693 if( BDB_IDL_IS_ZERO( ids ) )
697 ber_bvarray_free_x( keys, op->o_tmpmemctx );
700 LDAP_LOG ( INDEX, RESULTS,
701 "<= bdb_approx_candidates: id=%ld first=%ld last=%ld\n",
702 (long) ids[0], (long) BDB_IDL_FIRST( ids ),
703 (long) BDB_IDL_LAST( ids ) );
705 Debug( LDAP_DEBUG_TRACE, "<= bdb_approx_candidates %ld, first=%ld, last=%ld\n",
707 (long) BDB_IDL_FIRST(ids),
708 (long) BDB_IDL_LAST(ids) );
714 substring_candidates(
716 SubstringsAssertion *sub,
724 struct berval prefix = {0, NULL};
725 struct berval *keys = NULL;
729 LDAP_LOG ( INDEX, ENTRY, "=> bdb_substring_candidates (%s)\n",
730 sub->sa_desc->ad_cname.bv_val, 0, 0 );
732 Debug( LDAP_DEBUG_TRACE, "=> bdb_substring_candidates (%s)\n",
733 sub->sa_desc->ad_cname.bv_val, 0, 0 );
736 rc = bdb_index_param( op->o_bd, sub->sa_desc, LDAP_FILTER_SUBSTRINGS,
737 &db, &mask, &prefix );
739 if( rc != LDAP_SUCCESS ) {
741 LDAP_LOG ( INDEX, RESULTS,
742 "<= bdb_substring_candidates: (%s) "
743 "index_param failed (%d)\n",
744 sub->sa_desc->ad_cname.bv_val, rc, 0);
746 Debug( LDAP_DEBUG_ANY,
747 "<= bdb_substring_candidates: (%s) "
748 "index_param failed (%d)\n",
749 sub->sa_desc->ad_cname.bv_val, rc, 0 );
756 LDAP_LOG ( INDEX, RESULTS,
757 "<= bdb_substring_candidates: (%s) not indexed\n",
758 sub->sa_desc->ad_cname.bv_val, 0, 0 );
760 Debug( LDAP_DEBUG_ANY,
761 "<= bdb_substring_candidates: (%s) not indexed\n",
762 sub->sa_desc->ad_cname.bv_val, 0, 0 );
767 mr = sub->sa_desc->ad_type->sat_substr;
773 if( !mr->smr_filter ) {
777 rc = (mr->smr_filter)(
778 LDAP_FILTER_SUBSTRINGS,
780 sub->sa_desc->ad_type->sat_syntax,
784 &keys, op->o_tmpmemctx );
786 if( rc != LDAP_SUCCESS ) {
788 LDAP_LOG ( INDEX, RESULTS,
789 "<= bdb_substring_candidates: (%s) "
790 "MR filter failed (%d)\n",
791 sub->sa_desc->ad_cname.bv_val, rc, 0 );
793 Debug( LDAP_DEBUG_TRACE,
794 "<= bdb_substring_candidates: (%s) "
795 "MR filter failed (%d)\n",
796 sub->sa_desc->ad_cname.bv_val, rc, 0 );
803 LDAP_LOG ( INDEX, RESULTS,
804 "<= bdb_substring_candidates: (0x%04lx) no keys (%s)\n",
805 mask, sub->sa_desc->ad_cname.bv_val, 0 );
807 Debug( LDAP_DEBUG_TRACE,
808 "<= bdb_substring_candidates: (0x%04lx) no keys (%s)\n",
809 mask, sub->sa_desc->ad_cname.bv_val, 0 );
814 for ( i= 0; keys[i].bv_val != NULL; i++ ) {
815 rc = bdb_key_read( op->o_bd, db, NULL, &keys[i], tmp );
817 if( rc == DB_NOTFOUND ) {
821 } else if( rc != LDAP_SUCCESS ) {
823 LDAP_LOG ( INDEX, RESULTS,
824 "<= bdb_substring_candidates: (%s) "
825 "key read failed (%d)\n",
826 sub->sa_desc->ad_cname.bv_val, rc, 0 );
828 Debug( LDAP_DEBUG_TRACE,
829 "<= bdb_substring_candidates: (%s) "
830 "key read failed (%d)\n",
831 sub->sa_desc->ad_cname.bv_val, rc, 0 );
836 if( BDB_IDL_IS_ZERO( tmp ) ) {
838 LDAP_LOG ( INDEX, RESULTS,
839 "<= bdb_substring_candidates: (%s) NULL\n",
840 sub->sa_desc->ad_cname.bv_val, 0, 0 );
842 Debug( LDAP_DEBUG_TRACE,
843 "<= bdb_substring_candidates: (%s) NULL\n",
844 sub->sa_desc->ad_cname.bv_val, 0, 0 );
851 BDB_IDL_CPY( ids, tmp );
853 bdb_idl_intersection( ids, tmp );
856 if( BDB_IDL_IS_ZERO( ids ) )
860 ber_bvarray_free_x( keys, op->o_tmpmemctx );
863 LDAP_LOG ( INDEX, RESULTS,
864 "<= bdb_substring_candidates: id=%ld first=%ld last=%ld\n",
865 (long) ids[0], (long) BDB_IDL_FIRST( ids ),
866 (long) BDB_IDL_LAST( ids ) );
868 Debug( LDAP_DEBUG_TRACE, "<= bdb_substring_candidates: %ld, first=%ld, last=%ld\n",
870 (long) BDB_IDL_FIRST(ids),
871 (long) BDB_IDL_LAST(ids) );