From: Jong Hyuk Choi Date: Fri, 25 Oct 2002 17:51:30 +0000 (+0000) Subject: LCUP persistent search code drop X-Git-Tag: NO_SLAP_OP_BLOCKS~855 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=8074294f1d5aa59a0cb4a37a97285b5e15bb95a3;p=openldap LCUP persistent search code drop --- diff --git a/include/ldap.h b/include/ldap.h index 626e03746d..e34b9c4568 100644 --- a/include/ldap.h +++ b/include/ldap.h @@ -202,7 +202,9 @@ typedef struct ldapcontrol { #define LDAP_CONTROL_PAGEDRESULTS "1.2.840.113556.1.4.319" #endif +/* #define LDAP_CLIENT_UPDATE 1 +*/ #ifdef LDAP_CLIENT_UPDATE #define LDAP_CONTROL_CLIENT_UPDATE "1.3.6.1.4.1.4203.666.5.3" #define LDAP_CONTROL_ENTRY_UPDATE "1.3.6.1.4.1.4203.666.5.4" diff --git a/servers/slapd/Makefile.in b/servers/slapd/Makefile.in index 717b91dc70..1214f55812 100644 --- a/servers/slapd/Makefile.in +++ b/servers/slapd/Makefile.in @@ -19,7 +19,7 @@ SRCS = main.c daemon.c connection.c search.c filter.c add.c cr.c \ schemaparse.c ad.c at.c mr.c syntax.c oc.c saslauthz.c \ oidm.c starttls.c index.c sets.c referral.c \ root_dse.c sasl.c module.c suffixalias.c mra.c mods.c \ - limits.c backglue.c operational.c matchedValues.c \ + limits.c backglue.c operational.c matchedValues.c lcup.c \ $(@PLAT@_SRCS) OBJS = main.o daemon.o connection.o search.o filter.o add.o cr.o \ @@ -32,7 +32,7 @@ OBJS = main.o daemon.o connection.o search.o filter.o add.o cr.o \ schemaparse.o ad.o at.o mr.o syntax.o oc.o saslauthz.o \ oidm.o starttls.o index.o sets.o referral.o \ root_dse.o sasl.o module.o suffixalias.o mra.o mods.o \ - limits.o backglue.o operational.o matchedValues.o \ + limits.o backglue.o operational.o matchedValues.o lcup.o \ $(@PLAT@_OBJS) LDAP_INCDIR= ../../include diff --git a/servers/slapd/abandon.c b/servers/slapd/abandon.c index 80ea94be0c..5f2ac08275 100644 --- a/servers/slapd/abandon.c +++ b/servers/slapd/abandon.c @@ -30,9 +30,12 @@ do_abandon( Operation *op ) { - ber_int_t id; + ber_int_t id; Operation *o; - int rc; + int rc; +#ifdef LDAP_CLIENT_UPDATE + int i; +#endif #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ENTRY, "conn: %d do_abandon\n", conn->c_connid, 0, 0); @@ -105,6 +108,16 @@ do_abandon( } done: + +#if LDAP_CLIENT_UPDATE + for ( i = 0; i < nbackends; i++ ) { + if ( strncmp( backends[i].be_type, "bdb", 3 ) ) continue; + if ( bdb_abandon( &backends[i], conn, id ) == LDAP_SUCCESS ) { + break; + } + } +#endif + ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); #ifdef NEW_LOGGING diff --git a/servers/slapd/back-bdb/Makefile.in b/servers/slapd/back-bdb/Makefile.in index e7ecee8691..3644280e08 100644 --- a/servers/slapd/back-bdb/Makefile.in +++ b/servers/slapd/back-bdb/Makefile.in @@ -4,12 +4,12 @@ SRCS = init.c tools.c config.c \ add.c bind.c compare.c delete.c modify.c modrdn.c search.c \ extended.c passwd.c referral.c attribute.c group.c operational.c \ attr.c index.c key.c dbcache.c filterindex.c \ - dn2entry.c dn2id.c error.c id2entry.c idl.c nextid.c cache.c + dn2entry.c dn2id.c error.c id2entry.c idl.c nextid.c cache.c lcup.c OBJS = init.lo tools.lo config.lo \ add.lo bind.lo compare.lo delete.lo modify.lo modrdn.lo search.lo \ extended.lo passwd.lo referral.lo attribute.lo group.lo operational.lo \ attr.lo index.lo key.lo dbcache.lo filterindex.lo \ - dn2entry.lo dn2id.lo error.lo id2entry.lo idl.lo nextid.lo cache.lo + dn2entry.lo dn2id.lo error.lo id2entry.lo idl.lo nextid.lo cache.lo lcup.lo LDAP_INCDIR= ../../../include LDAP_LIBDIR= ../../../libraries diff --git a/servers/slapd/back-bdb/add.c b/servers/slapd/back-bdb/add.c index 76fac90435..286c44f864 100644 --- a/servers/slapd/back-bdb/add.c +++ b/servers/slapd/back-bdb/add.c @@ -42,6 +42,10 @@ bdb_add( #endif int noop = 0; +#ifdef LDAP_CLIENT_UPDATE + Operation* ps_list; +#endif + #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, ARGS, "==> bdb_add: %s\n", e->e_dn, 0, 0 ); #else @@ -458,6 +462,7 @@ retry: /* transaction retry */ goto return_results; } + if( op->o_noop ) { if (( rc=TXN_ABORT( ltid )) != 0 ) { text = "txn_abort (no-op) failed"; @@ -542,6 +547,14 @@ return_results: send_ldap_result( conn, op, rc, NULL, text, NULL, NULL ); +#ifdef LDAP_CLIENT_UPDATE + if ( rc == LDAP_SUCCESS && !noop ) { + LDAP_LIST_FOREACH ( ps_list, &bdb->psearch_list, link ) { + bdb_psearch( be, conn, op, ps_list, e, LCUP_PSEARCH_BY_ADD ); + } + } +#endif /* LDAP_CLIENT_UPDATE */ + if( rc == LDAP_SUCCESS && bdb->bi_txn_cp ) { ldap_pvt_thread_yield(); TXN_CHECKPOINT( bdb->bi_dbenv, @@ -557,3 +570,4 @@ done: return ( ( rc == LDAP_SUCCESS ) ? noop : rc ); } + diff --git a/servers/slapd/back-bdb/back-bdb.h b/servers/slapd/back-bdb/back-bdb.h index 56b4150330..7fea91c851 100644 --- a/servers/slapd/back-bdb/back-bdb.h +++ b/servers/slapd/back-bdb/back-bdb.h @@ -114,6 +114,9 @@ struct bdb_info { ID bi_lastid; ldap_pvt_thread_mutex_t bi_lastid_mutex; +#ifdef LDAP_CLIENT_UPDATE + LDAP_LIST_HEAD(pl, slap_op) psearch_list; +#endif }; #define bi_id2entry bi_databases[BDB_ID2ENTRY] diff --git a/servers/slapd/back-bdb/delete.c b/servers/slapd/back-bdb/delete.c index 5a19eb1e59..8d4c14e9c7 100644 --- a/servers/slapd/back-bdb/delete.c +++ b/servers/slapd/back-bdb/delete.c @@ -44,6 +44,10 @@ bdb_delete( int noop = 0; +#ifdef LDAP_CLIENT_UPDATE + Operation* ps_list; +#endif + #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, ARGS, "==> bdb_delete: %s\n", dn->bv_val, 0, 0 ); #else @@ -489,6 +493,14 @@ retry: /* transaction retry */ return_results: send_ldap_result( conn, op, rc, NULL, text, NULL, NULL ); +#ifdef LDAP_CLIENT_UPDATE + if ( rc == LDAP_SUCCESS && !noop ) { + LDAP_LIST_FOREACH( ps_list, &bdb->psearch_list, link ) { + bdb_psearch( be, conn, op, ps_list, e, LCUP_PSEARCH_BY_DELETE ); + } + } +#endif /* LDAP_CLIENT_UPDATE */ + if(rc == LDAP_SUCCESS && bdb->bi_txn_cp ) { ldap_pvt_thread_yield(); TXN_CHECKPOINT( bdb->bi_dbenv, diff --git a/servers/slapd/back-bdb/init.c b/servers/slapd/back-bdb/init.c index 7bd08c6726..0e3cab45de 100644 --- a/servers/slapd/back-bdb/init.c +++ b/servers/slapd/back-bdb/init.c @@ -93,6 +93,10 @@ bdb_db_init( BackendDB *be ) bdb->bi_lock_detect = DB_LOCK_DEFAULT; +#ifdef LDAP_CLIENT_UPDATE + LDAP_LIST_INIT (&bdb->psearch_list); +#endif + ldap_pvt_thread_mutex_init( &bdb->bi_database_mutex ); ldap_pvt_thread_mutex_init( &bdb->bi_lastid_mutex ); ldap_pvt_thread_mutex_init( &bdb->bi_cache.lru_mutex ); diff --git a/servers/slapd/back-bdb/modify.c b/servers/slapd/back-bdb/modify.c index 965bb0b098..3f267b0313 100644 --- a/servers/slapd/back-bdb/modify.c +++ b/servers/slapd/back-bdb/modify.c @@ -277,6 +277,12 @@ bdb_modify( int noop = 0; +#ifdef LDAP_CLIENT_UPDATE + Operation* ps_list; + struct psid_entry* pm_list; + struct psid_entry* pm_prev; +#endif + #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, ENTRY, "bdb_modify: %s\n", dn->bv_val, 0, 0 ); #else @@ -295,6 +301,17 @@ retry: /* transaction retry */ Debug(LDAP_DEBUG_TRACE, "bdb_modify: retrying...\n", 0, 0, 0); #endif + +#ifdef LDAP_CLIENT_UPDATE + pm_list = LDAP_LIST_FIRST(&op->premodify_list); + while ( pm_list != NULL ) { + LDAP_LIST_REMOVE ( pm_list, link ); + pm_prev = pm_list; + pm_list = LDAP_LIST_NEXT ( pm_list, link ); + free (pm_prev); + } +#endif + rc = TXN_ABORT( ltid ); ltid = NULL; op->o_private = NULL; @@ -405,6 +422,14 @@ retry: /* transaction retry */ ber_bvarray_free( refs ); goto done; } + +#ifdef LDAP_CLIENT_UPDATE + if ( rc == LDAP_SUCCESS && !op->o_noop ) { + LDAP_LIST_FOREACH ( ps_list, &bdb->psearch_list, link ) { + bdb_psearch(be, conn, op, ps_list, e, LCUP_PSEARCH_BY_PREMODIFY ); + } + } +#endif /* LDAP_CLIENT_UPDATE */ /* Modify the entry */ rc = bdb_modify_internal( be, conn, op, ltid, modlist, e, @@ -493,6 +518,24 @@ return_results: send_ldap_result( conn, op, rc, NULL, text, NULL, NULL ); +#ifdef LDAP_CLIENT_UPDATE + if ( rc == LDAP_SUCCESS && !op->o_noop ) { + /* Loop through in-scope entries for each psearch spec */ + LDAP_LIST_FOREACH ( ps_list, &bdb->psearch_list, link ) { + bdb_psearch( be, conn, op, ps_list, e, LCUP_PSEARCH_BY_MODIFY ); + } + pm_list = LDAP_LIST_FIRST(&op->premodify_list); + while ( pm_list != NULL ) { + bdb_psearch(be, conn, op, pm_list->ps->op, + e, LCUP_PSEARCH_BY_SCOPEOUT); + LDAP_LIST_REMOVE ( pm_list, link ); + pm_prev = pm_list; + pm_list = LDAP_LIST_NEXT ( pm_list, link ); + free (pm_prev); + } + } +#endif /* LDAP_CLIENT_UPDATE */ + if( rc == LDAP_SUCCESS && bdb->bi_txn_cp ) { ldap_pvt_thread_yield(); TXN_CHECKPOINT( bdb->bi_dbenv, @@ -501,6 +544,15 @@ return_results: done: if( ltid != NULL ) { +#ifdef LDAP_CLIENT_UPDATE + pm_list = LDAP_LIST_FIRST(&op->premodify_list); + while ( pm_list != NULL ) { + LDAP_LIST_REMOVE ( pm_list, link ); + pm_prev = pm_list; + pm_list = LDAP_LIST_NEXT ( pm_list, link ); + free (pm_prev); + } +#endif TXN_ABORT( ltid ); op->o_private = NULL; } diff --git a/servers/slapd/back-bdb/modrdn.c b/servers/slapd/back-bdb/modrdn.c index d55d0cb70c..7d3613fba1 100644 --- a/servers/slapd/back-bdb/modrdn.c +++ b/servers/slapd/back-bdb/modrdn.c @@ -62,6 +62,12 @@ bdb_modrdn( int noop = 0; +#ifdef LDAP_CLIENT_UPDATE + Operation* ps_list; + struct psid_entry* pm_list; + struct psid_entry* pm_prev; +#endif + #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, ENTRY, "==>bdb_modrdn(%s,%s,%s)\n", dn->bv_val,newrdn->bv_val, newSuperior ? newSuperior->bv_val : "NULL" ); @@ -88,6 +94,17 @@ retry: /* transaction retry */ #else Debug( LDAP_DEBUG_TRACE, "==>bdb_modrdn: retrying...\n", 0, 0, 0 ); #endif + +#ifdef LDAP_CLIENT_UPDATE + pm_list = LDAP_LIST_FIRST(&op->premodify_list); + while ( pm_list != NULL ) { + LDAP_LIST_REMOVE ( pm_list, link ); + pm_prev = pm_list; + pm_list = LDAP_LIST_NEXT ( pm_list, link ); + free (pm_prev); + } +#endif + rc = TXN_ABORT( ltid ); ltid = NULL; op->o_private = NULL; @@ -708,6 +725,14 @@ retry: /* transaction retry */ goto return_results; } +#ifdef LDAP_CLIENT_UPDATE + if ( rc == LDAP_SUCCESS && !op->o_noop ) { + LDAP_LIST_FOREACH ( ps_list, &bdb->psearch_list, link ) { + bdb_psearch(be, conn, op, ps_list, e, LCUP_PSEARCH_BY_PREMODIFY ); + } + } +#endif /* LDAP_CLIENT_UPDATE */ + /* modify entry */ rc = bdb_modify_internal( be, conn, op, ltid, &mod[0], e, &text, textbuf, textlen ); @@ -802,6 +827,24 @@ return_results: send_ldap_result( conn, op, rc, NULL, text, NULL, NULL ); +#ifdef LDAP_CLIENT_UPDATE + if ( rc == LDAP_SUCCESS && !op->o_noop ) { + /* Loop through in-scope entries for each psearch spec */ + LDAP_LIST_FOREACH ( ps_list, &bdb->psearch_list, link ) { + bdb_psearch( be, conn, op, ps_list, e, LCUP_PSEARCH_BY_MODIFY ); + } + pm_list = LDAP_LIST_FIRST(&op->premodify_list); + while ( pm_list != NULL ) { + bdb_psearch(be, conn, op, pm_list->ps->op, + e, LCUP_PSEARCH_BY_SCOPEOUT); + LDAP_LIST_REMOVE ( pm_list, link ); + pm_prev = pm_list; + pm_list = LDAP_LIST_NEXT ( pm_list, link ); + free (pm_prev); + } + } +#endif /* LDAP_CLIENT_UPDATE */ + if( rc == LDAP_SUCCESS && bdb->bi_txn_cp ) { ldap_pvt_thread_yield(); TXN_CHECKPOINT( bdb->bi_dbenv, @@ -844,6 +887,15 @@ done: } if( ltid != NULL ) { +#ifdef LDAP_CLIENT_UPDATE + pm_list = LDAP_LIST_FIRST(&op->premodify_list); + while ( pm_list != NULL ) { + LDAP_LIST_REMOVE ( pm_list, link ); + pm_prev = pm_list; + pm_list = LDAP_LIST_NEXT ( pm_list, link ); + free (pm_prev); + } +#endif TXN_ABORT( ltid ); op->o_private = NULL; } diff --git a/servers/slapd/back-bdb/proto-bdb.h b/servers/slapd/back-bdb/proto-bdb.h index 6c7dfeb586..d3df97b10a 100644 --- a/servers/slapd/back-bdb/proto-bdb.h +++ b/servers/slapd/back-bdb/proto-bdb.h @@ -364,6 +364,40 @@ int bdb_cache_delete_entry( ); void bdb_cache_release_all( Cache *cache ); +#ifdef LDAP_CLIENT_UPDATE +int bdb_abandon( + BackendDB *be, + Connection *conn, + ber_int_t id +); + +int bdb_add_psearch_spec( + BackendDB *be, + Connection *conn, + Operation *op, + struct berval *base, + struct berval *nbase, + int scope, + int deref, + int slimit, + int tlimit, + Filter *filter, + struct berval *fstr, + AttributeName *attrs, + int attrsonly +); + +int bdb_psearch( + BackendDB *be, + Connection *conn, + Operation *op, + Operation *ps_op, + Entry *entry, + int psearch_type +); + +#endif + #ifdef BDB_REUSE_LOCKERS int bdb_locker_id( Operation *op, DB_ENV *env, int *locker ); diff --git a/servers/slapd/back-bdb/search.c b/servers/slapd/back-bdb/search.c index 91db533895..03a0a540bc 100644 --- a/servers/slapd/back-bdb/search.c +++ b/servers/slapd/back-bdb/search.c @@ -81,6 +81,15 @@ bdb_search( 0, 0, 0); #endif +#ifdef LDAP_CLIENT_UPDATE + if ( op->o_clientupdate_type & SLAP_LCUP_PERSIST ) { + bdb_add_psearch_spec( be, conn, op, base, base, scope, + deref, slimit, tlimit, filter, filterstr, attrs, attrsonly ); + return LDAP_SUCCESS; + } +#endif + + manageDSAit = get_manageDSAit( op ); rc = LOCK_ID (bdb->bi_dbenv, &locker ); @@ -866,7 +875,7 @@ done: bdb_cache_return_entry_r ( bdb->bi_dbenv, &bdb->bi_cache, e, &lock ); } -#ifdef LDAP_CLIENT_UDATE +#ifdef LDAP_CLIENT_UPDATE if ( op->o_clientupdate_type & SLAP_LCUP_SYNC ) { if ( csnfeq.f_ava != NULL && csnfeq.f_av_value.bv_val != NULL ) { ch_free( csnfeq.f_av_value.bv_val ); diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c index 8d626aee56..3abf5fd841 100644 --- a/servers/slapd/connection.c +++ b/servers/slapd/connection.c @@ -1041,7 +1041,11 @@ operations_error: LDAP_STAILQ_REMOVE( &conn->c_ops, arg->co_op, slap_op, o_next); LDAP_STAILQ_NEXT(arg->co_op, o_next) = NULL; - slap_op_free( arg->co_op ); +#ifdef LDAP_CLIENT_UPDATE + if ( !( arg->co_op->o_clientupdate_type & SLAP_LCUP_PERSIST ) ) { + slap_op_free( arg->co_op ); + } +#endif /* LDAP_CLIENT_UPDATE */ arg->co_op = NULL; arg->co_conn = NULL; free( (char *) arg ); diff --git a/servers/slapd/controls.c b/servers/slapd/controls.c index 7c26ff1c38..acd9f6949f 100644 --- a/servers/slapd/controls.c +++ b/servers/slapd/controls.c @@ -318,6 +318,9 @@ int get_ctrls( case LDAP_REQ_UNBIND: tagmask = SLAP_CTRL_UNBIND; break; + case LDAP_REQ_ABANDON: + tagmask = SLAP_CTRL_ABANDON; + break; case LDAP_REQ_EXTENDED: /* FIXME: check list of extended operations */ tagmask = ~0U; diff --git a/servers/slapd/main.c b/servers/slapd/main.c index bda792fbf8..879588cbc2 100644 --- a/servers/slapd/main.c +++ b/servers/slapd/main.c @@ -395,6 +395,10 @@ int main( int argc, char **argv ) goto destroy; } +#ifdef LDAP_CLIENT_UPDATE + build_uuid_attr(); +#endif + #ifdef HAVE_TLS /* Library defaults to full certificate checking. This is correct when * a client is verifying a server because all servers should have a diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 7e9acb5d73..4a53b9034d 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -1057,6 +1057,14 @@ LDAP_SLAPD_F (int) value_add_one LDAP_P(( BerVarray *vals, struct berval *addval )); +/* + * lcup.c + */ + +extern AttributeName uuid_attr[2]; + +LDAP_SLAPD_F (int) build_uuid_attr LDAP_P ((void)); + /* * Other... */ diff --git a/servers/slapd/search.c b/servers/slapd/search.c index 9b4492ea11..4699633403 100644 --- a/servers/slapd/search.c +++ b/servers/slapd/search.c @@ -322,12 +322,17 @@ do_search( } return_results:; - if( pbase.bv_val != NULL) free( pbase.bv_val ); - if( nbase.bv_val != NULL) free( nbase.bv_val ); +#ifdef LDAP_CLIENT_UPDATE + if ( !( op->o_clientupdate_type & SLAP_LCUP_PERSIST ) ) +#endif /* LDAP_CLIENT_UPDATE */ + { + if( pbase.bv_val != NULL) free( pbase.bv_val ); + if( nbase.bv_val != NULL) free( nbase.bv_val ); - if( fstr.bv_val != NULL) free( fstr.bv_val ); - if( filter != NULL) filter_free( filter ); - if( an != NULL ) free( an ); + if( fstr.bv_val != NULL) free( fstr.bv_val ); + if( filter != NULL) filter_free( filter ); + if( an != NULL ) free( an ); + } return rc; } diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 0a27ab8706..eac214f3e2 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -1567,6 +1567,39 @@ typedef struct slap_paged_state { ID ps_id; } PagedResultsState; + +#ifdef LDAP_CLIENT_UPDATE +#define LCUP_PSEARCH_BY_ADD 0x01 +#define LCUP_PSEARCH_BY_DELETE 0x02 +#define LCUP_PSEARCH_BY_PREMODIFY 0x03 +#define LCUP_PSEARCH_BY_MODIFY 0x04 +#define LCUP_PSEARCH_BY_SCOPEOUT 0x05 + +struct lcup_search_spec { + struct slap_op *op; + struct berval *base; + struct berval *nbase; + int scope; + int deref; + int slimit; + int tlimit; + Filter *filter; + struct berval *filterstr; + AttributeName *attrs; + int attrsonly; + struct lcup_entry *elist; + ldap_pvt_thread_mutex_t elist_mutex; + int entry_count; + LDAP_LIST_ENTRY(lcup_search_spec) link; +}; + +struct psid_entry { + struct lcup_search_spec* ps; + LDAP_LIST_ENTRY(psid_entry) link; +}; +#endif /* LDAP_CLIENT_UPDATE */ + + /* * represents an operation pending from an ldap client */ @@ -1608,6 +1641,9 @@ typedef struct slap_op { #define SLAP_LCUP_SYNC_AND_PERSIST (0x3) ber_int_t o_clientupdate_interval; struct berval o_clientupdate_state; + LDAP_LIST_HEAD(lss, lcup_search_spec) psearch_spec; + LDAP_LIST_HEAD(pe, psid_entry) premodify_list; + LDAP_LIST_ENTRY(slap_op) link; #endif /* LDAP_CLIENT_UPDATE */ #ifdef LDAP_CONNECTIONLESS diff --git a/servers/slapd/tools/Makefile.in b/servers/slapd/tools/Makefile.in index 73780f68d6..c8d5ab782f 100644 --- a/servers/slapd/tools/Makefile.in +++ b/servers/slapd/tools/Makefile.in @@ -44,7 +44,7 @@ SLAPD_OBJS = ../config.o ../ch_malloc.o ../cr.o ../backend.o \ ../entry.o ../dn.o ../filter.o ../str2filter.o ../ava.o \ ../init.o ../controls.o ../kerberos.o ../passwd.o \ ../index.o ../extended.o ../starttls.o ../sets.o ../mra.o \ - ../referral.o ../backglue.o ../oidm.o ../mods.o + ../referral.o ../backglue.o ../oidm.o ../mods.o ../operation.o ../lcup.o SLAPOBJS = $(SLAPD_OBJS) slapcommon.o mimic.o