*/
LDAP_SLAPD_F (int) read_config LDAP_P(( const char *fname, int depth ));
LDAP_SLAPD_F (void) config_destroy LDAP_P ((void));
+LDAP_SLAPD_F (char **) str2clist LDAP_P(( char ***, char *, const char * ));
/*
* connection.c
* ctxcsn.c
*/
+LDAP_SLAPD_V( const struct berval ) slap_ldapsync_bv;
+LDAP_SLAPD_V( const struct berval ) slap_ldapsync_cn_bv;
LDAP_SLAPD_F (void) slap_get_commit_csn LDAP_P(( Operation *, struct berval * ));
LDAP_SLAPD_F (void) slap_rewind_commit_csn LDAP_P(( Operation * ));
LDAP_SLAPD_F (void) slap_graduate_commit_csn LDAP_P(( Operation * ));
LDAP_SLAPD_V( const struct berval ) slap_unknown_bv;
LDAP_SLAPD_V( const struct berval ) slap_true_bv;
LDAP_SLAPD_V( const struct berval ) slap_false_bv;
-LDAP_SLAPD_V( const struct berval ) slap_ldapsync_bv;
-LDAP_SLAPD_V( const struct berval ) slap_ldapsync_cn_bv;
/*
* index.c
LDAP_SLAPD_F (int) do_extended LDAP_P((Operation *op, SlapReply *rs));
/*
- * syncrepl
+ * syncrepl.c
*/
+LDAP_SLAPD_V( const struct berval ) slap_syncrepl_bvc;
+LDAP_SLAPD_V( const struct berval ) slap_syncrepl_cn_bvc;
+
LDAP_SLAPD_V (struct runqueue_s) syncrepl_rq;
LDAP_SLAPD_F (void) init_syncrepl LDAP_P(());
LDAP_SLAPD_F (void*) do_syncrepl LDAP_P((void *, void *));
LDAP_SLAPD_F (int) ldap_sync_search LDAP_P((
- syncinfo_t *, LDAP *, LDAPControl **, LDAPControl **, int *));
+ syncinfo_t *, LDAP *, LDAPControl **,
+ LDAPControl **, int *));
LDAP_SLAPD_F (Entry*) syncrepl_message_to_entry LDAP_P((
- syncinfo_t *, LDAP *, Operation *, LDAPMessage *,
- Modifications **, int*, struct berval *, struct berval * ));
+ syncinfo_t *, LDAP *, Operation *, LDAPMessage *,
+ Modifications **, int*, struct berval *, struct berval * ));
LDAP_SLAPD_F (int) syncrepl_entry LDAP_P((
- syncinfo_t *, LDAP *, Operation*, Entry*,
- Modifications*,int, struct berval*, struct berval*, int ));
+ syncinfo_t *, LDAP *, Operation*, Entry*,
+ Modifications*,int, struct berval*, struct berval*, int ));
LDAP_SLAPD_F (void) syncrepl_updateCookie LDAP_P((
- syncinfo_t *, LDAP *, Operation *, struct berval *,
- struct berval * ));
-LDAP_SLAPD_F (char **) str2clist LDAP_P(( char ***, char *, const char * ));
-
-LDAP_SLAPD_F (void) syncrepl_add_glue LDAP_P(( syncinfo_t *, LDAP *, Operation*, Entry*,
- Modifications*, int, struct berval*, struct berval* ));
+ syncinfo_t *, LDAP *, Operation *, struct berval *,
+ struct berval * ));
+LDAP_SLAPD_F (void) syncrepl_add_glue LDAP_P(( syncinfo_t *, LDAP *,
+ Operation*, Entry*, Modifications*, int,
+ struct berval*, struct berval* ));
+LDAP_SLAPD_F (Entry*) slap_create_syncrepl_entry LDAP_P((
+ Backend *, struct berval *,
+ struct berval *, struct berval * ));
LDAP_END_DECL
#include "slapcommon.h"
static char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ];
+static const struct berval slap_syncrepl_bvc = BER_BVC("syncreplxxx");
+static const struct berval slap_syncrepl_cn_bvc = BER_BVC("cn=syncreplxxx");
+static struct berval slap_syncrepl_bv = BER_BVNULL;
+static struct berval slap_syncrepl_cn_bv = BER_BVNULL;
+
+struct subentryinfo {
+ struct berval cn;
+ struct berval ndn;
+ struct berval rdn;
+ struct berval cookie;
+ LDAP_SLIST_ENTRY( subentryinfo ) sei_next;
+};
int
main( int argc, char **argv )
size_t textlen = sizeof textbuf;
struct berval csn;
+ struct berval maxcsn = { 0, NULL };
+ struct berval ldifcsn = { 0, NULL };
+ int match;
+ int provider_subentry = 0;
+ struct subentryinfo *sei;
+ LDAP_SLIST_HEAD( consumer_subentry_slist, subentryinfo ) consumer_subentry;
+ Attribute *attr;
+ Entry *ctxcsn_e;
+ ID ctxcsn_id;
+ struct berval ctxcsn_ndn = { 0, NULL };
+ int ret;
+ struct berval bvtext;
+ int i;
#ifdef NEW_LOGGING
lutil_log_initialize(argc, argv );
#endif
slap_tool_init( "slapadd", SLAPADD, argc, argv );
+ LDAP_SLIST_INIT( &consumer_subentry );
+
if( !be->be_entry_open ||
!be->be_entry_close ||
!be->be_entry_put )
while( ldif_read_record( ldiffp, &lineno, &buf, &lmax ) ) {
Entry *e = str2entry( buf );
- struct berval bvtext;
/*
* Initialize text buffer
vals[0] = csn;
attr_merge( e, slap_schema.si_ad_entryCSN, vals, NULL );
}
- }
- if (!dryrun) {
- ID id = be->be_entry_put( be, e, &bvtext );
- if( id == NOID ) {
- fprintf( stderr, "%s: could not add entry dn=\"%s\" (line=%d): %s\n",
- progname, e->e_dn, lineno, bvtext.bv_val );
- rc = EXIT_FAILURE;
- entry_free( e );
- if( continuemode ) continue;
- break;
+ if ( !is_entry_syncProviderSubentry( e ) &&
+ !is_entry_syncConsumerSubentry( e ) &&
+ update_ctxcsn != SLAP_TOOL_CTXCSN_KEEP ) {
+ attr = attr_find( e->e_attrs, slap_schema.si_ad_entryCSN );
+ if ( maxcsn.bv_len != 0 ) {
+ value_match( &match, slap_schema.si_ad_entryCSN,
+ slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
+ SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+ &maxcsn, &attr->a_nvals[0], &text );
+ } else {
+ match = -1;
+ }
+ if ( match < 0 ) {
+ if ( maxcsn.bv_val )
+ ch_free( maxcsn.bv_val );
+ ber_dupbv( &maxcsn, &attr->a_nvals[0] );
+ }
}
+ }
+
+ if ( update_ctxcsn == SLAP_TOOL_CTXCSN_KEEP ) {
+ if ( is_entry_syncProviderSubentry( e )) {
+ if ( !LDAP_SLIST_EMPTY( &consumer_subentry )) {
+ fprintf( stderr, "%s: consumer and provider subentries "
+ "are both present\n", progname );
+ rc = EXIT_FAILURE;
+ entry_free( e );
+ sei = LDAP_SLIST_FIRST( &consumer_subentry );
+ while ( sei ) {
+ ch_free( sei->cn.bv_val );
+ ch_free( sei->ndn.bv_val );
+ ch_free( sei->rdn.bv_val );
+ ch_free( sei->cookie.bv_val );
+ LDAP_SLIST_REMOVE_HEAD( &consumer_subentry, sei_next );
+ ch_free( sei );
+ sei = LDAP_SLIST_FIRST( &consumer_subentry );
+ }
+ break;
+ }
+ if ( provider_subentry ) {
+ fprintf( stderr, "%s: multiple provider subentries are "
+ "present : add -w flag to refresh\n", progname );
+ rc = EXIT_FAILURE;
+ entry_free( e );
+ break;
+ }
+ attr = attr_find( e->e_attrs, slap_schema.si_ad_contextCSN );
+ if ( attr == NULL ) {
+ entry_free( e );
+ continue;
+ }
+ provider_subentry = 1;
+ ber_dupbv( &maxcsn, &attr->a_nvals[0] );
+ } else if ( is_entry_syncConsumerSubentry( e )) {
+ if ( provider_subentry ) {
+ fprintf( stderr, "%s: consumer and provider subentries "
+ "are both present\n", progname );
+ rc = EXIT_FAILURE;
+ entry_free( e );
+ break;
+ }
- if ( verbose ) {
- fprintf( stderr, "added: \"%s\" (%08lx)\n",
- e->e_dn, (long) id );
+ attr = attr_find( e->e_attrs, slap_schema.si_ad_cn );
+
+ if ( attr == NULL ) {
+ entry_free( e );
+ continue;
+ }
+
+ if ( !LDAP_SLIST_EMPTY( &consumer_subentry )) {
+ LDAP_SLIST_FOREACH( sei, &consumer_subentry, sei_next ) {
+ value_match( &match, slap_schema.si_ad_cn,
+ slap_schema.si_ad_cn->ad_type->sat_equality,
+ SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+ &sei->cn, &attr->a_nvals[0], &text );
+ }
+ if ( !match ) {
+ fprintf( stderr, "%s: multiple consumer subentries "
+ "have the same id : add -w flag to refresh\n",
+ progname );
+ rc = EXIT_FAILURE;
+ entry_free( e );
+ sei = LDAP_SLIST_FIRST( &consumer_subentry );
+ while ( sei ) {
+ ch_free( sei->cn.bv_val );
+ ch_free( sei->ndn.bv_val );
+ ch_free( sei->rdn.bv_val );
+ ch_free( sei->cookie.bv_val );
+ LDAP_SLIST_REMOVE_HEAD( &consumer_subentry, sei_next );
+ ch_free( sei );
+ sei = LDAP_SLIST_FIRST( &consumer_subentry );
+ }
+ break;
+ }
+ }
+ sei = ch_calloc( 1, sizeof( struct subentryinfo ));
+ ber_dupbv( &sei->cn, &attr->a_nvals[0] );
+ ber_dupbv( &sei->ndn, &e->e_nname );
+ dnExtractRdn( &sei->ndn, &sei->rdn, NULL );
+ attr = attr_find( e->e_attrs, slap_schema.si_ad_syncreplCookie );
+ if ( attr == NULL ) {
+ ch_free( sei->cn.bv_val );
+ ch_free( sei->ndn.bv_val );
+ ch_free( sei->rdn.bv_val );
+ ch_free( sei->cookie.bv_val );
+ ch_free( sei );
+ entry_free( e );
+ continue;
+ }
+ ber_dupbv( &sei->cookie, &attr->a_nvals[0] );
+ LDAP_SLIST_INSERT_HEAD( &consumer_subentry, sei, sei_next );
}
- } else {
- if ( verbose ) {
- fprintf( stderr, "(dry) added: \"%s\"\n", e->e_dn );
+ }
+
+ if ( !is_entry_syncProviderSubentry( e ) &&
+ !is_entry_syncConsumerSubentry( e )) {
+ if (!dryrun) {
+ ID id = be->be_entry_put( be, e, &bvtext );
+ if( id == NOID ) {
+ fprintf( stderr, "%s: could not add entry dn=\"%s\" "
+ "(line=%d): %s\n", progname, e->e_dn,
+ lineno, bvtext.bv_val );
+ rc = EXIT_FAILURE;
+ entry_free( e );
+ if( continuemode ) continue;
+ break;
+ }
+
+ if ( verbose ) {
+ fprintf( stderr, "added: \"%s\" (%08lx)\n",
+ e->e_dn, (long) id );
+ }
+ } else {
+ if ( verbose ) {
+ fprintf( stderr, "(dry) added: \"%s\"\n", e->e_dn );
+ }
}
}
entry_free( e );
}
- if ( SLAP_LASTMOD(be) && update_ctxcsn == SLAP_TOOL_CTXCSN_BATCH && csn.bv_len > 0 ) {
- Entry *ctxcsn_e;
- ID ctxcsn_id;
- struct berval ctxcsn_ndn = { 0, NULL };
- int ret;
- struct berval bvtext;
- Attribute *attr;
-
- bvtext.bv_len = textlen;
- bvtext.bv_val = textbuf;
- bvtext.bv_val[0] = '\0';
+ bvtext.bv_len = textlen;
+ bvtext.bv_val = textbuf;
+ bvtext.bv_val[0] = '\0';
+
+ if ( !LDAP_SLIST_EMPTY( &consumer_subentry )) {
+ maxcsn.bv_len = 0;
+ maxcsn.bv_val = NULL;
+ LDAP_SLIST_FOREACH( sei, &consumer_subentry, sei_next ) {
+ if ( maxcsn.bv_len != 0 ) {
+ value_match( &match, slap_schema.si_ad_syncreplCookie,
+ slap_schema.si_ad_syncreplCookie->ad_type->sat_ordering,
+ SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+ &maxcsn, &sei->cookie, &text );
+ } else {
+ match = -1;
+ }
+ if ( match < 0 ) {
+ if ( maxcsn.bv_val )
+ ch_free( maxcsn.bv_val );
+ ber_dupbv( &maxcsn, &sei->cookie );
+ }
+ }
+ }
- build_new_dn( &ctxcsn_ndn, &be->be_nsuffix[0], (struct berval *)&slap_ldapsync_cn_bv, NULL );
- ctxcsn_id = be->be_dn2id_get( be, &ctxcsn_ndn );
+ if ( SLAP_LASTMOD(be) && replica_promotion ) {
+ if ( provider_subentry || update_ctxcsn == SLAP_TOOL_CTXCSN_BATCH ||
+ !LDAP_SLIST_EMPTY( &consumer_subentry )) {
+ build_new_dn( &ctxcsn_ndn, &be->be_nsuffix[0],
+ (struct berval *)&slap_ldapsync_cn_bv, NULL );
+ ctxcsn_id = be->be_dn2id_get( be, &ctxcsn_ndn );
- if ( ctxcsn_id == NOID ) {
- ctxcsn_e = slap_create_context_csn_entry( be, &csn );
- ctxcsn_id = be->be_entry_put( be, ctxcsn_e, &bvtext );
- if( ctxcsn_id == NOID ) {
- fprintf( stderr, "%s: could not add ctxcsn subentry\n", progname);
- rc = EXIT_FAILURE;
- }
- if ( verbose ) {
- fprintf( stderr, "added: \"%s\" (%08lx)\n", ctxcsn_e->e_dn, (long) ctxcsn_id );
+ if ( ctxcsn_id == NOID ) {
+ ctxcsn_e = slap_create_context_csn_entry( be, &maxcsn );
+ if ( !dryrun ) {
+ ctxcsn_id = be->be_entry_put( be, ctxcsn_e, &bvtext );
+ if( ctxcsn_id == NOID ) {
+ fprintf( stderr, "%s: could not add ctxcsn subentry\n",
+ progname);
+ rc = EXIT_FAILURE;
+ }
+ if ( verbose ) {
+ fprintf( stderr, "added: \"%s\" (%08lx)\n",
+ ctxcsn_e->e_dn, (long) ctxcsn_id );
+ }
+ } else {
+ if ( verbose ) {
+ fprintf( stderr, "(dry) added: \"%s\"\n", ctxcsn_e->e_dn );
+ }
+ }
+ entry_free( ctxcsn_e );
+ } else {
+ ret = be->be_id2entry_get( be, ctxcsn_id, &ctxcsn_e );
+ if ( ret == LDAP_SUCCESS ) {
+ attr = attr_find( ctxcsn_e->e_attrs,
+ slap_schema.si_ad_contextCSN );
+ AC_MEMCPY( attr->a_vals[0].bv_val, maxcsn.bv_val, maxcsn.bv_len );
+ attr->a_vals[0].bv_val[maxcsn.bv_len] = '\0';
+ attr->a_vals[0].bv_len = maxcsn.bv_len;
+ if ( !dryrun ) {
+ ctxcsn_id = be->be_entry_modify( be, ctxcsn_e, &bvtext );
+ if( ctxcsn_id == NOID ) {
+ fprintf( stderr, "%s: could not modify ctxcsn "
+ "subentry\n", progname);
+ rc = EXIT_FAILURE;
+ }
+ if ( verbose ) {
+ fprintf( stderr, "modified: \"%s\" (%08lx)\n",
+ ctxcsn_e->e_dn, (long) ctxcsn_id );
+ }
+ } else {
+ if ( verbose ) {
+ fprintf( stderr, "(dry) modified: \"%s\"\n",
+ ctxcsn_e->e_dn );
+ }
+ }
+ } else {
+ fprintf( stderr, "%s: could not modify ctxcsn subentry\n",
+ progname);
+ rc = EXIT_FAILURE;
+ }
}
- entry_free( ctxcsn_e );
- } else {
- ret = be->be_id2entry_get( be, ctxcsn_id, &ctxcsn_e );
- if ( ret == LDAP_SUCCESS ) {
- attr = attr_find( ctxcsn_e->e_attrs, slap_schema.si_ad_contextCSN );
- attr->a_vals[0] = csn;
- ctxcsn_id = be->be_entry_modify( be, ctxcsn_e, &bvtext );
- if( ctxcsn_id == NOID ) {
- fprintf( stderr, "%s: could not modify ctxcsn subentry\n", progname);
+ }
+ } else if ( SLAP_LASTMOD(be) && replica_demotion &&
+ ( update_ctxcsn == SLAP_TOOL_CTXCSN_BATCH ||
+ provider_subentry )) {
+
+ ber_dupbv( &slap_syncrepl_bv, (struct berval *) &slap_syncrepl_bvc );
+ ber_dupbv( &slap_syncrepl_cn_bv,
+ (struct berval *) &slap_syncrepl_cn_bvc );
+
+ if ( replica_id_list == NULL ) {
+ replica_id_list = ch_calloc( 2, sizeof( int ));
+ replica_id_list[0] = 0;
+ replica_id_list[1] = -1;
+ }
+
+ for ( i = 0; replica_id_list[i] > -1 ; i++ ) {
+ slap_syncrepl_bv.bv_len = snprintf( slap_syncrepl_bv.bv_val,
+ slap_syncrepl_bvc.bv_len,
+ "syncrepl%d", replica_id_list[i] );
+ slap_syncrepl_cn_bv.bv_len = snprintf( slap_syncrepl_cn_bv.bv_val,
+ slap_syncrepl_cn_bvc.bv_len,
+ "cn=syncrepl%d", replica_id_list[i] );
+ build_new_dn( &ctxcsn_ndn, &be->be_nsuffix[0],
+ (struct berval *)&slap_syncrepl_cn_bv, NULL );
+ ctxcsn_id = be->be_dn2id_get( be, &ctxcsn_ndn );
+
+ if ( ctxcsn_id == NOID ) {
+ ctxcsn_e = slap_create_syncrepl_entry( be, &maxcsn,
+ &slap_syncrepl_cn_bv,
+ &slap_syncrepl_bv );
+ if ( !dryrun ) {
+ ctxcsn_id = be->be_entry_put( be, ctxcsn_e, &bvtext );
+ if( ctxcsn_id == NOID ) {
+ fprintf( stderr, "%s: could not add ctxcsn subentry\n",
+ progname);
+ rc = EXIT_FAILURE;
+ }
+ if ( verbose ) {
+ fprintf( stderr, "added: \"%s\" (%08lx)\n",
+ ctxcsn_e->e_dn, (long) ctxcsn_id );
+ }
+ } else {
+ if ( verbose ) {
+ fprintf( stderr, "(dry) added: \"%s\"\n",
+ ctxcsn_e->e_dn );
+ }
+ }
+ entry_free( ctxcsn_e );
+ } else {
+ ret = be->be_id2entry_get( be, ctxcsn_id, &ctxcsn_e );
+ if ( ret == LDAP_SUCCESS ) {
+ attr = attr_find( ctxcsn_e->e_attrs,
+ slap_schema.si_ad_syncreplCookie );
+ AC_MEMCPY( attr->a_vals[0].bv_val, maxcsn.bv_val, maxcsn.bv_len );
+ attr->a_vals[0].bv_val[maxcsn.bv_len] = '\0';
+ attr->a_vals[0].bv_len = maxcsn.bv_len;
+ if ( !dryrun ) {
+ ctxcsn_id = be->be_entry_modify( be,
+ ctxcsn_e, &bvtext );
+ if( ctxcsn_id == NOID ) {
+ fprintf( stderr, "%s: could not modify ctxcsn "
+ "subentry\n", progname);
+ rc = EXIT_FAILURE;
+ }
+ if ( verbose ) {
+ fprintf( stderr, "modified: \"%s\" (%08lx)\n",
+ ctxcsn_e->e_dn, (long) ctxcsn_id );
+ }
+ } else {
+ if ( verbose ) {
+ fprintf( stderr, "(dry) modified: \"%s\"\n",
+ ctxcsn_e->e_dn );
+ }
+ }
+ } else {
+ fprintf( stderr, "%s: could not modify ctxcsn subentry\n",
+ progname);
rc = EXIT_FAILURE;
}
- if ( verbose ) {
- fprintf( stderr, "modified: \"%s\" (%08lx)\n", ctxcsn_e->e_dn, (long) ctxcsn_id );
+ }
+ }
+
+ if ( slap_syncrepl_bv.bv_val ) {
+ ch_free( slap_syncrepl_bv.bv_val );
+ }
+ if ( slap_syncrepl_cn_bv.bv_val ) {
+ ch_free( slap_syncrepl_cn_bv.bv_val );
+ }
+ } else if ( SLAP_LASTMOD(be) && replica_demotion &&
+ !LDAP_SLIST_EMPTY( &consumer_subentry )) {
+
+ LDAP_SLIST_FOREACH( sei, &consumer_subentry, sei_next ) {
+ ctxcsn_id = be->be_dn2id_get( be, &sei->ndn );
+
+ if ( ctxcsn_id == NOID ) {
+ ctxcsn_e = slap_create_syncrepl_entry( be, &sei->cookie,
+ &sei->rdn, &sei->cn );
+ if ( !dryrun ) {
+ ctxcsn_id = be->be_entry_put( be, ctxcsn_e, &bvtext );
+ if( ctxcsn_id == NOID ) {
+ fprintf( stderr, "%s: could not add ctxcsn subentry\n",
+ progname);
+ rc = EXIT_FAILURE;
+ }
+ if ( verbose ) {
+ fprintf( stderr, "added: \"%s\" (%08lx)\n",
+ ctxcsn_e->e_dn, (long) ctxcsn_id );
+ }
+ } else {
+ if ( verbose ) {
+ fprintf( stderr, "(dry) added: \"%s\"\n",
+ ctxcsn_e->e_dn );
+ }
}
+ entry_free( ctxcsn_e );
} else {
- fprintf( stderr, "%s: could not modify ctxcsn subentry\n", progname);
- rc = EXIT_FAILURE;
+ ret = be->be_id2entry_get( be, ctxcsn_id, &ctxcsn_e );
+ if ( ret == LDAP_SUCCESS ) {
+ attr = attr_find( ctxcsn_e->e_attrs,
+ slap_schema.si_ad_syncreplCookie );
+ AC_MEMCPY( attr->a_vals[0].bv_val, maxcsn.bv_val, maxcsn.bv_len );
+ attr->a_vals[0].bv_val[maxcsn.bv_len] = '\0';
+ attr->a_vals[0].bv_len = maxcsn.bv_len;
+ if ( !dryrun ) {
+ ctxcsn_id = be->be_entry_modify( be,
+ ctxcsn_e, &bvtext );
+ if( ctxcsn_id == NOID ) {
+ fprintf( stderr, "%s: could not modify ctxcsn "
+ "subentry\n", progname);
+ rc = EXIT_FAILURE;
+ }
+ if ( verbose ) {
+ fprintf( stderr, "modified: \"%s\" (%08lx)\n",
+ ctxcsn_e->e_dn, (long) ctxcsn_id );
+ }
+ } else {
+ if ( verbose ) {
+ fprintf( stderr, "(dry) modified: \"%s\"\n",
+ ctxcsn_e->e_dn );
+ }
+ }
+ } else {
+ fprintf( stderr, "%s: could not modify ctxcsn subentry\n",
+ progname);
+ rc = EXIT_FAILURE;
+ }
}
}
+
+ if ( slap_syncrepl_bv.bv_val ) {
+ ch_free( slap_syncrepl_bv.bv_val );
+ }
+ if ( slap_syncrepl_cn_bv.bv_val ) {
+ ch_free( slap_syncrepl_cn_bv.bv_val );
+ }
+ }
+
+ sei = LDAP_SLIST_FIRST( &consumer_subentry );
+ while ( sei ) {
+ ch_free( sei->cn.bv_val );
+ ch_free( sei->ndn.bv_val );
+ ch_free( sei->rdn.bv_val );
+ ch_free( sei->cookie.bv_val );
+ LDAP_SLIST_REMOVE_HEAD( &consumer_subentry, sei_next );
+ ch_free( sei );
+ sei = LDAP_SLIST_FIRST( &consumer_subentry );
}
ch_free( buf );