#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"
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 \
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
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);
}
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
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
#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
goto return_results;
}
+
if( op->o_noop ) {
if (( rc=TXN_ABORT( ltid )) != 0 ) {
text = "txn_abort (no-op) failed";
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,
return ( ( rc == LDAP_SUCCESS ) ? noop : rc );
}
+
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]
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
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,
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 );
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
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;
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,
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,
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;
}
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" );
#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;
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 );
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,
}
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;
}
);
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 );
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 );
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 );
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 );
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;
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
BerVarray *vals,
struct berval *addval ));
+/*
+ * lcup.c
+ */
+
+extern AttributeName uuid_attr[2];
+
+LDAP_SLAPD_F (int) build_uuid_attr LDAP_P ((void));
+
/*
* Other...
*/
}
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;
}
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
*/
#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
../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