LDAP Sync Operation (draft-zeilenga-ldup-sync) as a groundwork for an LDAP replication design

This commit is contained in:
Jong Hyuk Choi 2003-02-05 07:37:02 +00:00
parent 1b4401ff53
commit 85b1783d5c
19 changed files with 1346 additions and 476 deletions

View File

@ -76,6 +76,10 @@ usage( void )
* " sp/<cint>/<cookie>/<slimit>\n"
* */
#endif
#ifdef LDAP_SYNC
" [!]sync= ro[/<cookie>] (ldap sync - refreshOnly)\n"
" rp[/<cookie>][/<slimit>] (ldap sync - refreshAndPersist)\n"
#endif
" -F prefix URL prefix for files (default: %s)\n"
" -l limit time limit (in seconds) for search\n"
" -L print responses in LDIFv1 format\n"
@ -147,11 +151,20 @@ static int includeufn, vals2tmp = 0, ldif = 0;
static int subentries = 0, valuesReturnFilter = 0;
static char *vrFilter = NULL;
#ifdef LDAP_CLIENT_UPDATE
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
static int lcup = 0;
static int ldapsync = 0;
#endif
#ifdef LDAP_CLIENT_UPDATE
static int lcup_cint = 0;
static struct berval lcup_cookie = { 0, NULL };
static int lcup_slimit = 0;
static int lcup_slimit = -1;
#endif
#ifdef LDAP_SYNC
static struct berval sync_cookie = { 0, NULL };
static int sync_slimit = -1;
#endif
static int pagedResults = 0;
@ -290,29 +303,35 @@ handle_private_option( int i )
#endif
#ifdef LDAP_CLIENT_UPDATE
} else if ( strcasecmp( control, "lcup" ) == 0 ) {
char *cookiep;
char *slimitp;
if ( lcup ) {
fprintf( stderr, "client update control previously specified\n");
exit( EXIT_FAILURE );
}
if ( cvalue == NULL ) {
fprintf( stderr,
"missing specification of client update control\n");
exit( EXIT_FAILURE );
}
if ( strncasecmp( cvalue, "p", 1 ) == 0 ) {
lcup = LDAP_CUP_PERSIST_ONLY;
cvalue += 2;
cookiep = strchr( cvalue, '/' );
*cookiep++ = '\0';
lcup_cint = atoi( cvalue );
cvalue = cookiep;
slimitp = strchr( cvalue, '/' );
*slimitp++ = '\0';
ber_str2bv( cookiep, 0, 0, &lcup_cookie );
lcup_slimit = atoi( slimitp );
} else if ( strcasecmp( control, "lcup" ) == 0 ) {
char *cookiep;
char *slimitp;
if ( lcup ) {
fprintf( stderr, "client update control previously specified\n");
exit( EXIT_FAILURE );
}
if ( ldapsync != -1 ) {
fprintf( stderr, "ldap sync control previously specified\n");
exit( EXIT_FAILURE );
}
if ( cvalue == NULL ) {
fprintf( stderr,
"missing specification of client update control\n");
exit( EXIT_FAILURE );
}
if ( strncasecmp( cvalue, "p", 1 ) == 0 ) {
lcup = LDAP_CUP_PERSIST_ONLY;
cvalue = strchr( cvalue, '/' );
cvalue++;
cookiep = strchr( cvalue, '/' );
*cookiep++ = '\0';
lcup_cint = atoi( cvalue );
cvalue = cookiep;
slimitp = strchr( cvalue, '/' );
*slimitp++ = '\0';
while ( isspace( *cookiep ) ) cookiep++;
ber_str2bv( cookiep, 0, 0, &lcup_cookie );
lcup_slimit = atoi( slimitp );
/*
} else if ( strncasecmp( cvalue, "s", 1 ) == 0 ) {
lcup = LDAP_CUP_SYNC_ONLY;
@ -342,6 +361,56 @@ handle_private_option( int i )
if ( crit ) lcup *= -1;
#endif
#ifdef LDAP_SYNC
} else if ( strcasecmp( control, "sync" ) == 0 ) {
char *cookiep;
char *slimitp;
if ( ldapsync ) {
fprintf( stderr, "ldap sync control previously specified\n" );
exit( EXIT_FAILURE );
}
if ( lcup ) {
fprintf( stderr, "client update control previously specified\n" );
exit( EXIT_FAILURE );
}
if ( cvalue == NULL ) {
fprintf( stderr,
"missing specification of ldap sync control\n");
exit( EXIT_FAILURE );
}
if ( strncasecmp( cvalue, "ro", 2 ) == 0 ) {
ldapsync = LDAP_SYNC_REFRESH_ONLY;
cookiep = strchr( cvalue, '/' );
if ( cookiep != NULL ) {
cookiep++;
if ( *cookiep != '\0' ) {
ber_str2bv( cookiep, 0, 0, &sync_cookie );
}
}
} else if ( strncasecmp( cvalue, "rp", 2 ) == 0 ) {
ldapsync = LDAP_SYNC_REFRESH_AND_PERSIST;
cookiep = strchr( cvalue, '/' );
if ( cookiep != NULL ) {
*cookiep++ = '\0';
cvalue = cookiep;
}
slimitp = strchr( cvalue, '/' );
if ( slimitp != NULL ) {
*slimitp++ = '\0';
}
if ( cookiep != NULL && *cookiep != '\0' )
ber_str2bv( cookiep, 0, 0, &sync_cookie );
if ( slimitp != NULL && *slimitp != '\0' )
sync_slimit = atoi( slimitp );
} else {
fprintf( stderr,
"ldap sync control value \"%s\" invalid\n",
cvalue );
exit( EXIT_FAILURE );
}
if ( crit ) ldapsync *= -1;
#endif
} else {
fprintf( stderr, "Invalid control name: %s\n", control );
usage();
@ -434,6 +503,11 @@ main( int argc, char **argv )
struct berval *cubvalp = NULL;
#endif
#ifdef LDAP_SYNC
BerElement *syncber = NULL;
struct berval *syncbvalp = NULL;
#endif
npagedresponses = npagedentries = npagedreferences =
npagedextended = npagedpartial = 0;
@ -530,7 +604,10 @@ getNextPage:
|| valuesReturnFilter || pageSize
#ifdef LDAP_CLIENT_UPDATE
|| lcup
#endif /* LDAP_CLIENT_UPDATE */
#endif
#ifdef LDAP_SYNC
|| ldapsync
#endif
) {
int err;
int i=0;
@ -560,25 +637,61 @@ getNextPage:
#endif
#ifdef LDAP_CLIENT_UPDATE
if ( lcup ) {
if (( cuber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
if ( lcup ) {
if (( cuber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
return EXIT_FAILURE;
}
if ( lcup_cookie.bv_len == 0 ) {
err = ber_printf( cuber, "{ei}", abs(lcup), lcup_cint );
} else {
err = ber_printf( cuber, "{ei{sO}}", abs(lcup), lcup_cint,
LDAP_LCUP_COOKIE_OID, &lcup_cookie );
}
if ( err == LBER_ERROR ) {
ber_free( cuber, 1 );
fprintf( stderr, "client update control encoding error!\n" );
return EXIT_FAILURE;
}
if ( ber_flatten( cuber, &cubvalp ) == LBER_ERROR ) {
return EXIT_FAILURE;
}
c[i].ldctl_oid = LDAP_CONTROL_CLIENT_UPDATE;
c[i].ldctl_value = (*cubvalp);
c[i].ldctl_iscritical = lcup < 0;
i++;
}
#endif
#ifdef LDAP_SYNC
if ( ldapsync ) {
if (( syncber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
return EXIT_FAILURE;
}
err = ber_printf( cuber, "{ei{sO}}", abs(lcup), lcup_cint,
LDAP_CLIENT_UPDATE_COOKIE, &lcup_cookie);
if ( sync_cookie.bv_len == 0 ) {
err = ber_printf( syncber, "{e}", abs(ldapsync) );
} else {
err = ber_printf( syncber, "{eO}", abs(ldapsync),
&sync_cookie );
}
if ( err == LBER_ERROR ) {
ber_free( cuber, 1 );
fprintf( stderr, "client update control encoding error!\n" );
ber_free( syncber, 1 );
fprintf( stderr, "ldap sync control encoding error!\n" );
return EXIT_FAILURE;
}
if ( ber_flatten( cuber, &cubvalp ) == LBER_ERROR ) {
if ( ber_flatten( syncber, &syncbvalp ) == LBER_ERROR ) {
return EXIT_FAILURE;
}
c[i].ldctl_oid = LDAP_CONTROL_CLIENT_UPDATE;
c[i].ldctl_value=(*cubvalp);
c[i].ldctl_iscritical = lcup < 0;
c[i].ldctl_oid = LDAP_CONTROL_SYNC;
c[i].ldctl_value = (*syncbvalp);
c[i].ldctl_iscritical = ldapsync < 0;
i++;
}
#endif
@ -776,7 +889,13 @@ static int dosearch(
int nextended;
int npartial;
LDAPMessage *res, *msg;
ber_int_t msgid;
ber_int_t msgid;
#ifdef LDAP_SYNC
char *retoid = NULL;
struct berval *retdata = NULL;
int nresponses_psearch = -1;
int cancel_msgid = -1;
#endif
if( filtpatt != NULL ) {
filter = malloc( strlen( filtpatt ) + strlen( value ) );
@ -806,6 +925,8 @@ static int dosearch(
rc = ldap_search_ext( ld, base, scope, filter, attrs, attrsonly,
sctrls, cctrls, timeout, sizelimit, &msgid );
printf("msgid = %d\n", msgid);
if ( filtpatt != NULL ) {
free( filter );
}
@ -833,7 +954,11 @@ static int dosearch(
msg != NULL;
msg = ldap_next_message( ld, msg ) )
{
if( nresponses++ ) putchar('\n');
if ( nresponses++ ) putchar('\n');
#if LDAP_SYNC
if ( nresponses_psearch >= 0 )
nresponses_psearch++;
#endif
switch( ldap_msgtype( msg ) ) {
case LDAP_RES_SEARCH_ENTRY:
@ -854,6 +979,16 @@ static int dosearch(
/* unsolicited extended operation */
goto done;
}
#ifdef LDAP_SYNC
if ( cancel_msgid != -1 &&
cancel_msgid == ldap_msgid( msg ) ) {
printf("Cancelled \n");
printf("cancel_msgid = %d\n", cancel_msgid);
goto done;
}
#endif
break;
case LDAP_RES_EXTENDED_PARTIAL:
@ -866,14 +1001,62 @@ static int dosearch(
if ( pageSize != 0 ) {
rc = parse_page_control( ld, msg, &cookie );
}
goto done;
}
#ifdef LDAP_CLIENT_UPDATE
if ( nresponses >= lcup_slimit ) {
if ( lcup == LDAP_CUP_PERSIST_ONLY ||
lcup == LDAP_CUP_SYNC_AND_PERSIST ) {
break;
}
#endif
#if defined(LDAP_CLIENT_UPDATE) && defined(LDAP_SYNC)
else
#endif
#ifdef LDAP_SYNC
if ( ldapsync == LDAP_SYNC_REFRESH_AND_PERSIST ) {
break;
}
#endif
goto done;
#ifdef LDAP_SYNC
case LDAP_RES_INTERMEDIATE_RESP:
ldap_parse_intermediate_resp_result( ld, msg, &retoid, &retdata, 0 );
nresponses_psearch = 0;
if ( strcmp( retoid, LDAP_SYNC_INFO ) ) {
printf("Unexpected Intermediate Response\n");
ldap_memfree( retoid );
ber_bvfree( retdata );
goto done;
} else {
printf("SyncInfo Received\n");
ldap_memfree( retoid );
ber_bvfree( retdata );
break;
}
#endif
}
#ifdef LDAP_CLIENT_UPDATE
if ( lcup && lcup_slimit != -1 && nresponses >= lcup_slimit ) {
ldap_abandon (ld, ldap_msgid(msg));
goto done;
}
#endif
#ifdef LDAP_SYNC
if ( ldapsync && sync_slimit != -1 &&
nresponses_psearch >= sync_slimit ) {
BerElement *msgidber = NULL;
struct berval *msgidvalp = NULL;
msgidber = ber_alloc_t(LBER_USE_DER);
ber_printf(msgidber, "{i}", msgid);
ber_flatten(msgidber, &msgidvalp);
ldap_extended_operation(ld, LDAP_EXOP_X_CANCEL,
msgidvalp, NULL, NULL, &cancel_msgid);
nresponses_psearch = -1;
}
#endif
}

View File

@ -205,11 +205,29 @@ typedef struct ldapcontrol {
/*
#define LDAP_CLIENT_UPDATE 1
#define LDAP_SYNC 2
*/
#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"
#define LDAP_CONTROL_CLIENT_UPDATE_DONE "1.3.6.1.4.1.4203.666.5.5"
#define LDAP_CONTROL_CLIENT_UPDATE_DONE "1.3.6.1.4.1.4203.666.5.5"
#define LDAP_LCUP_COOKIE_OID "1.3.6.1.4.1.4203.666.10.1"
#endif
#ifdef LDAP_SYNC
#define LDAP_CONTROL_SYNC "1.3.6.1.4.1.4203.666.5.TBD1"
#define LDAP_CONTROL_SYNC_STATE "1.3.6.1.4.1.4203.666.5.TBD2"
#define LDAP_CONTROL_SYNC_DONE "1.3.6.1.4.1.4203.666.5.TBD3"
#define LDAP_SYNC_INFO "1.3.6.1.4.1.4203.666.5.TBD4"
#define LDAP_SYNC_REFRESH_DONE 0
#define LDAP_SYNC_NEW_COOKIE 1
#define LDAP_SYNC_PRESENT 0
#define LDAP_SYNC_ADD 1
#define LDAP_SYNC_MODIFY 2
#define LDAP_SYNC_DELETE 3
#endif
#define LDAP_CONTROL_SORTREQUEST "1.2.840.113556.1.4.473"
@ -278,8 +296,12 @@ typedef struct ldapcontrol {
#define LDAP_TAG_LDAPCRED ((ber_tag_t) 0x04U) /* octet string */
#ifdef LDAP_CLIENT_UPDATE
#define LDAP_TAG_COOKIE ((ber_tag_t) 0x30U) /* sequence */
#endif /* LDAP_CLIENT_UPDATE */
#define LDAP_LCUP_TAG_COOKIE ((ber_tag_t) 0x30U) /* sequence */
#endif
#ifdef LDAP_SYNC
#define LDAP_SYNC_TAG_COOKIE ((ber_tag_t) 0x04U) /* octet string */
#endif
#define LDAP_TAG_CONTROLS ((ber_tag_t) 0xa0U) /* context specific + constructed + 0 */
#define LDAP_TAG_REFERRAL ((ber_tag_t) 0xa3U) /* context specific + constructed + 3 */
@ -477,15 +499,7 @@ typedef struct ldapcontrol {
#define LDAP_CUP_UNSUPPORTED_SCHEME 0x65
#define LDAP_CUP_CLIENT_DISCONNECT 0x66
#define LDAP_CUP_RELOAD_REQUIRED 0x67
/* LCUP update type */
#define LDAP_CUP_SYNC_ONLY 0x00
#define LDAP_CUP_SYNC_AND_PERSIST 0x01
#define LDAP_CUP_PERSIST_ONLY 0x02
/* LCUP default cookie interval */
#define LDAP_CUP_DEFAULT_SEND_COOKIE_INTERVAL 0x01
#endif /* LDAP_CLIENT_UPDATE */
#endif
/* resultCode for Cancel Response */
#define LDAP_CANCELLED 0x68
@ -498,6 +512,24 @@ typedef struct ldapcontrol {
#define LDAP_CANCEL_ACK 0x02
#define LDAP_CANCEL_DONE 0x03
#ifdef LDAP_CLIENT_UPDATE
/* LCUP update type */
#define LDAP_CUP_NONE 0x00
#define LDAP_CUP_SYNC_ONLY 0x01
#define LDAP_CUP_PERSIST_ONLY 0x02
#define LDAP_CUP_SYNC_AND_PERSIST 0x03
/* LCUP default cookie interval */
#define LDAP_CUP_DEFAULT_SEND_COOKIE_INTERVAL 0x01
#endif /* LDAP_CLIENT_UPDATE */
/* LDAP SYNC request type */
#ifdef LDAP_SYNC
#define LDAP_SYNC_NONE 0x00
#define LDAP_SYNC_REFRESH_ONLY 0x01
#define LDAP_SYNC_REFRESH_AND_PERSIST 0x03
#endif
/*
* This structure represents both ldap messages and ldap responses.
* These are really the same, except in the case of search responses,

View File

@ -92,6 +92,18 @@ static struct ldaperror ldap_builtin_errlist[] = {
{LDAP_MORE_RESULTS_TO_RETURN, "More results to return" },
{LDAP_CLIENT_LOOP, "Client Loop" },
{LDAP_REFERRAL_LIMIT_EXCEEDED, "Referral Limit Exceeded" },
#ifdef LDAP_CLIENT_UPDATE
{LDAP_CUP_RESOURCES_EXHAUSTED, "LDAP Client Update Resource Exhausted" },
{LDAP_CUP_SECURITY_VIOLATION, "LDAP Client Update Security Violation" },
{LDAP_CUP_INVALID_COOKIE, "LDAP Client Update Invalid Cookie" },
{LDAP_CUP_UNSUPPORTED_SCHEME, "LDAP Client Update Unsupported Scheme" },
{LDAP_CUP_CLIENT_DISCONNECT, "LDAP Client Update Client Disconnect" },
{LDAP_CUP_RELOAD_REQUIRED, "LDAP Client Update Reload Required" },
#endif
{LDAP_CANCELLED, "LDAP Cancelled" },
{LDAP_NO_SUCH_OPERATION, "LDAP No Operation to Cancel" },
{LDAP_TOO_LATE, "LDAP Too Late to Cancel" },
{LDAP_CANNOT_CANCEL, "LDAP Cannot Cancel" },
{-1, NULL}
};

View File

@ -109,7 +109,7 @@ do_abandon(
done:
#if LDAP_CLIENT_UPDATE
#ifdef 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 ) {

View File

@ -42,7 +42,7 @@ bdb_add(
#endif
int noop = 0;
#ifdef LDAP_CLIENT_UPDATE
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
Operation* ps_list;
#endif
@ -547,10 +547,10 @@ return_results:
send_ldap_result( conn, op, rc,
NULL, text, NULL, NULL );
#ifdef LDAP_CLIENT_UPDATE
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
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 );
bdb_psearch( be, conn, op, ps_list, e, LDAP_PSEARCH_BY_ADD );
}
}
#endif /* LDAP_CLIENT_UPDATE */

View File

@ -132,7 +132,7 @@ struct bdb_info {
ID bi_lastid;
ldap_pvt_thread_mutex_t bi_lastid_mutex;
#ifdef LDAP_CLIENT_UPDATE
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
LDAP_LIST_HEAD(pl, slap_op) psearch_list;
#endif
#ifdef SLAP_IDL_CACHE

View File

@ -44,7 +44,7 @@ bdb_delete(
int noop = 0;
#ifdef LDAP_CLIENT_UPDATE
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
Operation* ps_list;
#endif
@ -493,13 +493,13 @@ retry: /* transaction retry */
return_results:
send_ldap_result( conn, op, rc, NULL, text, NULL, NULL );
#ifdef LDAP_CLIENT_UPDATE
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
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 );
bdb_psearch( be, conn, op, ps_list, e, LDAP_PSEARCH_BY_DELETE );
}
}
#endif /* LDAP_CLIENT_UPDATE */
#endif
if(rc == LDAP_SUCCESS && bdb->bi_txn_cp ) {
ldap_pvt_thread_yield();

View File

@ -95,7 +95,7 @@ bdb_db_init( BackendDB *be )
bdb->bi_search_stack_depth = DEFAULT_SEARCH_STACK_DEPTH;
bdb->bi_search_stack = NULL;
#ifdef LDAP_CLIENT_UPDATE
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
LDAP_LIST_INIT (&bdb->psearch_list);
#endif

View File

@ -13,20 +13,25 @@
#include "idl.h"
#include "external.h"
#ifdef LDAP_CLIENT_UPDATE
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
#define IS_BDB_REPLACE (( psearch_type == LDAP_PSEARCH_BY_DELETE ) || \
( psearch_type == LDAP_PSEARCH_BY_SCOPEOUT ))
#define IS_BDB_LCUP_REPLACE (( protocol == LDAP_CLIENT_UPDATE ) && IS_BDB_REPLACE )
static int psearch_base_candidate(
BackendDB *be,
Entry *e,
Entry *e,
ID *ids );
static int psearch_candidates(
BackendDB *be,
Operation *op,
Entry *e,
Filter *filter,
int scope,
int deref,
ID *ids );
BackendDB *be,
Operation *op,
Entry *e,
Filter *filter,
int scope,
int deref,
ID *ids );
int
bdb_abandon(
@ -50,6 +55,39 @@ bdb_abandon(
return LDAP_UNAVAILABLE;
}
int
bdb_cancel(
BackendDB *be,
Connection *conn,
ber_int_t id )
{
Operation *ps_list;
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
LDAP_LIST_FOREACH ( ps_list, &bdb->psearch_list, link ) {
if ( ps_list->o_connid == conn->c_connid ) {
if ( ps_list->o_msgid == id ) {
ps_list->o_cancel = LDAP_CANCEL_DONE;
LDAP_LIST_REMOVE( ps_list, link );
#if 0
bdb_build_sync_done_ctrl( conn, ps_list, ps_list->ctrls, 1, &latest_entrycsn_bv );
send_search_result( conn, ps_list, LDAP_CANCELLED,
NULL, NULL, NULL, ps_list->ctrls, ps_list->nentries);
#endif
send_search_result( conn, ps_list, LDAP_CANCELLED,
NULL, NULL, NULL, NULL, 0);
slap_op_free ( ps_list );
return LDAP_SUCCESS;
}
}
}
return LDAP_UNAVAILABLE;
}
int
bdb_add_psearch_spec(
BackendDB *be,
@ -64,30 +102,33 @@ bdb_add_psearch_spec(
Filter *filter,
struct berval *fstr,
AttributeName *attrs,
int attrsonly )
int attrsonly,
int protocol )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
LDAP_LIST_FIRST(&op->psearch_spec) = (struct lcup_search_spec *)
calloc ( 1, sizeof ( struct lcup_search_spec ) );
LDAP_LIST_FIRST( &op->psearch_spec ) = (struct ldap_psearch_spec *)
calloc ( 1, sizeof ( struct ldap_psearch_spec ) );
LDAP_LIST_FIRST(&op->psearch_spec)->op = op;
LDAP_LIST_FIRST( &op->psearch_spec )->op = op;
LDAP_LIST_FIRST(&op->psearch_spec)->base = ber_dupbv(NULL, base);
LDAP_LIST_FIRST(&op->psearch_spec)->nbase = ber_dupbv(NULL, nbase);
LDAP_LIST_FIRST( &op->psearch_spec )->base = ber_dupbv(NULL, base);
LDAP_LIST_FIRST( &op->psearch_spec )->nbase = ber_dupbv(NULL, nbase);
LDAP_LIST_FIRST(&op->psearch_spec)->scope = scope;
LDAP_LIST_FIRST(&op->psearch_spec)->deref = deref;
LDAP_LIST_FIRST(&op->psearch_spec)->slimit = slimit;
LDAP_LIST_FIRST(&op->psearch_spec)->tlimit = tlimit;
LDAP_LIST_FIRST( &op->psearch_spec )->scope = scope;
LDAP_LIST_FIRST( &op->psearch_spec )->deref = deref;
LDAP_LIST_FIRST( &op->psearch_spec )->slimit = slimit;
LDAP_LIST_FIRST( &op->psearch_spec )->tlimit = tlimit;
LDAP_LIST_FIRST(&op->psearch_spec)->filter = filter;
LDAP_LIST_FIRST(&op->psearch_spec)->filterstr = ber_dupbv(NULL, fstr);
LDAP_LIST_FIRST(&op->psearch_spec)->attrs = attrs;
LDAP_LIST_FIRST( &op->psearch_spec )->filter = filter;
LDAP_LIST_FIRST( &op->psearch_spec )->filterstr = ber_dupbv(NULL, fstr);
LDAP_LIST_FIRST( &op->psearch_spec )->attrs = attrs;
LDAP_LIST_FIRST(&op->psearch_spec)->attrsonly = attrsonly;
LDAP_LIST_FIRST( &op->psearch_spec )->attrsonly = attrsonly;
LDAP_LIST_FIRST(&op->psearch_spec)->entry_count = 0;
LDAP_LIST_FIRST( &op->psearch_spec )->entry_count = 0;
LDAP_LIST_FIRST( &op->psearch_spec )->protocol = protocol;
LDAP_LIST_INSERT_HEAD( &bdb->psearch_list, op, link );
}
@ -99,26 +140,29 @@ bdb_psearch(
Operation *op,
Operation *ps_op,
Entry *entry,
int psearch_type )
int psearch_type )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
int rc;
const char *text = NULL;
const char *text = NULL;
time_t stoptime;
unsigned cursor;
ID id;
ID candidates[BDB_IDL_UM_SIZE];
Entry *e = NULL;
BerVarray v2refs = NULL;
Entry *matched = NULL;
BerVarray v2refs = NULL;
Entry *matched = NULL;
struct berval realbase = { 0, NULL };
int nentries = 0;
int manageDSAit;
Filter lcupf, csnfnot, csnfeq, csnfand, csnfge;
AttributeAssertion aa_ge, aa_eq;
struct berval entrycsn_bv = { 0, NULL };
struct berval latest_entrycsn_bv = { 0, NULL };
Filter cookief, csnfnot, csnfeq, csnfand, csnfge;
AttributeAssertion aa_ge, aa_eq;
struct berval entrycsn_bv = { 0, NULL };
struct berval latest_entrycsn_bv = { 0, NULL };
LDAPControl *ctrls[SLAP_SEARCH_MAX_CTRLS];
int num_ctrls = 0;
struct slap_limits_set *limit = NULL;
int isroot = 0;
@ -128,31 +172,18 @@ bdb_psearch(
DB_LOCK lock;
Connection *ps_conn = ps_op->o_conn;
struct berval *base = LDAP_LIST_FIRST(&ps_op->psearch_spec)->base;
struct berval *nbase = LDAP_LIST_FIRST(&ps_op->psearch_spec)->nbase;
int scope = LDAP_LIST_FIRST(&ps_op->psearch_spec)->scope;
int deref = LDAP_LIST_FIRST(&ps_op->psearch_spec)->deref;
int slimit = LDAP_LIST_FIRST(&ps_op->psearch_spec)->slimit;
int tlimit = LDAP_LIST_FIRST(&ps_op->psearch_spec)->tlimit;
Filter *filter = LDAP_LIST_FIRST(&ps_op->psearch_spec)->filter;
struct berval *filterstr = LDAP_LIST_FIRST(&ps_op->psearch_spec)->filterstr;
int attrsonly = LDAP_LIST_FIRST(&ps_op->psearch_spec)->attrsonly;
struct berval *base = LDAP_LIST_FIRST( &ps_op->psearch_spec )->base;
struct berval *nbase = LDAP_LIST_FIRST( &ps_op->psearch_spec )->nbase;
int scope = LDAP_LIST_FIRST( &ps_op->psearch_spec )->scope;
int deref = LDAP_LIST_FIRST( &ps_op->psearch_spec )->deref;
int slimit = LDAP_LIST_FIRST( &ps_op->psearch_spec )->slimit;
int tlimit = LDAP_LIST_FIRST( &ps_op->psearch_spec )->tlimit;
Filter *filter = LDAP_LIST_FIRST( &ps_op->psearch_spec )->filter;
struct berval *filterstr = LDAP_LIST_FIRST( &ps_op->psearch_spec )->filterstr;
int attrsonly = LDAP_LIST_FIRST( &ps_op->psearch_spec )->attrsonly;
int protocol = LDAP_LIST_FIRST( &ps_op->psearch_spec )->protocol;
AttributeName uuid_attr[2];
AttributeName *attrs = uuid_attr;
if ( psearch_type != LCUP_PSEARCH_BY_DELETE &&
psearch_type != LCUP_PSEARCH_BY_SCOPEOUT )
{
attrs = LDAP_LIST_FIRST(&ps_op->psearch_spec)->attrs;
} else {
attrs[0].an_desc = slap_schema.si_ad_entryUUID;
attrs[0].an_oc = NULL;
ber_dupbv( &attrs[0].an_name, &attrs[0].an_desc->ad_cname );
attrs[1].an_desc = NULL;
attrs[1].an_oc = NULL;
attrs[1].an_name.bv_len = 0;
attrs[1].an_name.bv_val = NULL;
}
AttributeName *attrs;
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ENTRY, "bdb_back_search\n", 0, 0, 0 );
@ -170,10 +201,41 @@ bdb_psearch(
default:
send_ldap_result( ps_conn, ps_op, rc=LDAP_OTHER,
NULL, "internal error", NULL, NULL );
if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
ch_free( attrs[0].an_name.bv_val );
return rc;
}
for ( num_ctrls = 0; num_ctrls < SLAP_SEARCH_MAX_CTRLS; num_ctrls++ )
ctrls[num_ctrls] = NULL;
num_ctrls = 0;
if ( !IS_BDB_REPLACE ) {
attrs = LDAP_LIST_FIRST(&ps_op->psearch_spec)->attrs;
} else {
#ifdef LDAP_CLIENT_UPDATE
if ( protocol == LDAP_CLIENT_UPDATE ) {
attrs = uuid_attr;
attrs[0].an_desc = slap_schema.si_ad_entryUUID;
attrs[0].an_oc = NULL;
ber_dupbv( &attrs[0].an_name, &attrs[0].an_desc->ad_cname );
attrs[1].an_desc = NULL;
attrs[1].an_oc = NULL;
attrs[1].an_name.bv_len = 0;
attrs[1].an_name.bv_val = NULL;
} else
#endif
#ifdef LDAP_SYNC
if (protocol == LDAP_SYNC ) {
attrs = uuid_attr;
attrs[0].an_desc = NULL;
attrs[0].an_oc = NULL;
attrs[0].an_name.bv_len = 0;
attrs[0].an_name.bv_val = NULL;
} else
#endif
{
rc = 1;
goto done;
}
}
if ( nbase->bv_len == 0 ) {
@ -209,9 +271,10 @@ dn2entry_retry:
send_ldap_result( ps_conn, ps_op, LDAP_BUSY,
NULL, "ldap server busy", NULL, NULL );
LOCK_ID_FREE( bdb->bi_dbenv, locker );
if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
#ifdef LDAP_CLIENT_UPDATE
if ( IS_BDB_LCUP_REPLACE )
ch_free( attrs[0].an_name.bv_val );
#endif
return LDAP_BUSY;
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
@ -228,9 +291,10 @@ dn2entry_retry:
send_ldap_result( ps_conn, ps_op, rc=LDAP_OTHER,
NULL, "internal error", NULL, NULL );
LOCK_ID_FREE( bdb->bi_dbenv, locker );
if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
#ifdef LDAP_CLIENT_UPDATE
if ( IS_BDB_LCUP_REPLACE )
ch_free( attrs[0].an_name.bv_val );
#endif
return rc;
}
@ -267,9 +331,10 @@ dn2entry_retry:
LOCK_ID_FREE( bdb->bi_dbenv, locker );
if ( refs ) ber_bvarray_free( refs );
if ( matched_dn.bv_val ) ber_memfree( matched_dn.bv_val );
if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
#ifdef LDAP_CLIENT_UPDATE
if ( IS_BDB_LCUP_REPLACE )
ch_free( attrs[0].an_name.bv_val );
#endif
return rc;
}
@ -307,9 +372,10 @@ dn2entry_retry:
LOCK_ID_FREE( bdb->bi_dbenv, locker );
ber_bvarray_free( refs );
ber_memfree( matched_dn.bv_val );
if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
#ifdef LDAP_CLIENT_UPDATE
if ( IS_BDB_LCUP_REPLACE )
ch_free( attrs[0].an_name.bv_val );
#endif
return 1;
}
@ -444,28 +510,61 @@ dn2entry_retry:
}
}
lcupf.f_choice = LDAP_FILTER_AND;
lcupf.f_and = &csnfnot;
lcupf.f_next = NULL;
#ifdef LDAP_CLIENT_UPDATE
if ( protocol == LDAP_CLIENT_UPDATE ) {
cookief.f_choice = LDAP_FILTER_AND;
cookief.f_and = &csnfnot;
cookief.f_next = NULL;
csnfnot.f_choice = LDAP_FILTER_NOT;
csnfnot.f_not = &csnfeq;
csnfnot.f_next = &csnfand;
csnfnot.f_choice = LDAP_FILTER_NOT;
csnfnot.f_not = &csnfeq;
csnfnot.f_next = &csnfand;
csnfeq.f_choice = LDAP_FILTER_EQUALITY;
csnfeq.f_ava = &aa_eq;
csnfeq.f_av_desc = slap_schema.si_ad_entryCSN;
ber_dupbv( &csnfeq.f_av_value, &ps_op->o_clientupdate_state );
csnfeq.f_choice = LDAP_FILTER_EQUALITY;
csnfeq.f_ava = &aa_eq;
csnfeq.f_av_desc = slap_schema.si_ad_entryCSN;
ber_dupbv( &csnfeq.f_av_value, &ps_op->o_clientupdate_state );
csnfand.f_choice = LDAP_FILTER_AND;
csnfand.f_and = &csnfge;
csnfand.f_next = NULL;
csnfge.f_choice = LDAP_FILTER_GE;
csnfge.f_ava = &aa_ge;
csnfge.f_av_desc = slap_schema.si_ad_entryCSN;
ber_dupbv( &csnfge.f_av_value, &ps_op->o_clientupdate_state );
csnfge.f_next = filter;
}
#endif
#if defined(LDAP_CLIENT_UPDATE) && defined(LDAP_SYNC)
else
#endif
#ifdef LDAP_SYNC
if ( protocol == LDAP_SYNC ) {
cookief.f_choice = LDAP_FILTER_AND;
cookief.f_and = &csnfnot;
cookief.f_next = NULL;
csnfnot.f_choice = LDAP_FILTER_NOT;
csnfnot.f_not = &csnfeq;
csnfnot.f_next = &csnfand;
csnfand.f_choice = LDAP_FILTER_AND;
csnfand.f_and = &csnfge;
csnfand.f_next = NULL;
csnfeq.f_choice = LDAP_FILTER_EQUALITY;
csnfeq.f_ava = &aa_eq;
csnfeq.f_av_desc = slap_schema.si_ad_entryCSN;
ber_dupbv( &csnfeq.f_av_value, &ps_op->o_sync_state );
csnfge.f_choice = LDAP_FILTER_GE;
csnfge.f_ava = &aa_ge;
csnfge.f_av_desc = slap_schema.si_ad_entryCSN;
ber_dupbv( &csnfge.f_av_value, &ps_op->o_clientupdate_state );
csnfge.f_next = filter;
csnfand.f_choice = LDAP_FILTER_AND;
csnfand.f_and = &csnfge;
csnfand.f_next = NULL;
csnfge.f_choice = LDAP_FILTER_GE;
csnfge.f_ava = &aa_ge;
csnfge.f_av_desc = slap_schema.si_ad_entryCSN;
ber_dupbv( &csnfge.f_av_value, &ps_op->o_sync_state );
csnfge.f_next = filter;
}
#endif
id = entry->e_id;
@ -604,8 +703,8 @@ dn2entry_retry:
goto test_done;
}
if ( psearch_type != LCUP_PSEARCH_BY_SCOPEOUT ) {
rc = test_filter( be, ps_conn, ps_op, e, &lcupf );
if ( psearch_type != LDAP_PSEARCH_BY_SCOPEOUT ) {
rc = test_filter( be, ps_conn, ps_op, e, &cookief );
} else {
rc = LDAP_COMPARE_TRUE;
}
@ -647,144 +746,87 @@ dn2entry_retry:
} else
#endif
{
if ( psearch_type == LCUP_PSEARCH_BY_ADD ||
psearch_type == LCUP_PSEARCH_BY_DELETE ||
psearch_type == LCUP_PSEARCH_BY_MODIFY ||
psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
#ifdef LDAP_SYNC
int premodify_found = 0;
int entry_sync_state;
#endif
if ( psearch_type == LDAP_PSEARCH_BY_ADD ||
psearch_type == LDAP_PSEARCH_BY_DELETE ||
psearch_type == LDAP_PSEARCH_BY_MODIFY ||
psearch_type == LDAP_PSEARCH_BY_SCOPEOUT )
{
Attribute* a;
int ret;
int res;
const char *text = NULL;
LDAPControl *ctrls[2];
struct berval *bv;
char berbuf[LBER_ELEMENT_SIZEOF];
BerElement *ber = (BerElement *)berbuf;
ber_init2( ber, NULL, LBER_USE_DER );
LDAP_LIST_FIRST(&ps_op->psearch_spec)->entry_count++;
ctrls[0] = ch_malloc ( sizeof ( LDAPControl ) );
ctrls[1] = NULL;
if ( LDAP_LIST_FIRST(
&ps_op->psearch_spec)->entry_count %
ps_op->o_clientupdate_interval == 0 )
{
/* Send cookie */
for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
AttributeDescription *desc = a->a_desc;
if ( desc == slap_schema.si_ad_entryCSN ) {
ber_dupbv( &entrycsn_bv, &a->a_vals[0] );
if ( latest_entrycsn_bv.bv_val == NULL ) {
ber_dupbv( &latest_entrycsn_bv,
&entrycsn_bv );
} else {
res = value_match( &ret, desc,
desc->ad_type->sat_ordering,
SLAP_MR_ASSERTION_SYNTAX_MATCH,
&entrycsn_bv, &latest_entrycsn_bv,
&text );
if ( res != LDAP_SUCCESS ) {
ret = 0;
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, RESULTS,
"bdb_search: "
"value_match failed\n",
0, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"bdb_search: "
"value_match failed\n",
0, 0, 0 );
#endif
}
if ( ret > 0 ) {
ch_free(latest_entrycsn_bv.bv_val);
latest_entrycsn_bv.bv_val = NULL;
ber_dupbv( &latest_entrycsn_bv,
&entrycsn_bv );
}
}
}
}
if ( psearch_type != LCUP_PSEARCH_BY_DELETE ||
psearch_type != LCUP_PSEARCH_BY_SCOPEOUT )
{
ber_printf( ber, "{bb{sON}N}",
SLAP_LCUP_STATE_UPDATE_FALSE,
SLAP_LCUP_ENTRY_DELETED_FALSE,
LCUP_COOKIE_OID, &entrycsn_bv );
} else {
ber_printf( ber, "{bb{sON}N}",
SLAP_LCUP_STATE_UPDATE_FALSE,
SLAP_LCUP_ENTRY_DELETED_TRUE,
LCUP_COOKIE_OID, &entrycsn_bv );
}
ch_free( entrycsn_bv.bv_val );
entrycsn_bv.bv_val = NULL;
} else {
/* Do not send cookie */
if ( psearch_type != LCUP_PSEARCH_BY_DELETE ||
psearch_type != LCUP_PSEARCH_BY_SCOPEOUT )
{
ber_printf( ber, "{bbN}",
SLAP_LCUP_STATE_UPDATE_FALSE,
SLAP_LCUP_ENTRY_DELETED_FALSE );
} else {
ber_printf( ber, "{bbN}",
SLAP_LCUP_STATE_UPDATE_FALSE,
SLAP_LCUP_ENTRY_DELETED_TRUE );
}
}
ctrls[0]->ldctl_oid = LDAP_CONTROL_ENTRY_UPDATE;
ctrls[0]->ldctl_iscritical = ps_op->o_clientupdate;
ret = ber_flatten2( ber, &ctrls[0]->ldctl_value, 0 );
if ( ret < 0 ) {
ber_free_buf( ber );
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, RESULTS,
"bdb_search: ber_flatten2 failed\n",
0, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"bdb_search: ber_flatten2 failed\n",
0, 0, 0 );
#endif
send_ldap_result( ps_conn, ps_op, rc=LDAP_OTHER,
NULL, "internal error", NULL, NULL );
goto done;
}
result = send_search_entry( be, ps_conn, ps_op,
e, attrs, attrsonly, ctrls);
ber_free_buf( ber );
ch_free( ctrls[0] );
if ( psearch_type == LCUP_PSEARCH_BY_MODIFY ) {
if ( psearch_type == LDAP_PSEARCH_BY_MODIFY ) {
struct psid_entry* psid_e;
LDAP_LIST_FOREACH( psid_e, &op->premodify_list,
link)
LDAP_LIST_FOREACH( psid_e, &op->premodify_list, link)
{
if( psid_e->ps ==
LDAP_LIST_FIRST(&ps_op->psearch_spec))
if( psid_e->ps == LDAP_LIST_FIRST(&ps_op->psearch_spec))
{
#ifdef LDAP_SYNC
premodify_found = 1;
#endif
LDAP_LIST_REMOVE(psid_e, link);
break;
}
}
if (psid_e != NULL) free (psid_e);
}
#ifdef LDAP_SYNC
if ( psearch_type == LDAP_PSEARCH_BY_ADD )
entry_sync_state = LDAP_SYNC_ADD;
else if ( psearch_type == LDAP_PSEARCH_BY_DELETE )
entry_sync_state = LDAP_SYNC_DELETE;
else if ( psearch_type == LDAP_PSEARCH_BY_MODIFY ) {
if ( premodify_found )
entry_sync_state = LDAP_SYNC_MODIFY;
else
entry_sync_state = LDAP_SYNC_ADD;
} else if ( psearch_type == LDAP_PSEARCH_BY_SCOPEOUT )
entry_sync_state = LDAP_SYNC_DELETE;
else {
rc = 1;
goto done;
}
#endif
} else if ( psearch_type == LCUP_PSEARCH_BY_PREMODIFY ) {
#ifdef LDAP_CLIENT_UPDATE
if ( protocol == LDAP_CLIENT_UPDATE ) {
int entry_count = ++(LDAP_LIST_FIRST(&ps_op->psearch_spec)->entry_count);
if ( IS_BDB_REPLACE ) {
rc = bdb_build_lcup_update_ctrl( ps_conn, ps_op, e, entry_count, ctrls,
num_ctrls++, &latest_entrycsn_bv, SLAP_LCUP_ENTRY_DELETED_TRUE );
} else {
rc = bdb_build_lcup_update_ctrl( ps_conn, ps_op, e, entry_count, ctrls,
num_ctrls++, &latest_entrycsn_bv, SLAP_LCUP_ENTRY_DELETED_FALSE );
}
if ( rc != LDAP_SUCCESS )
goto done;
result = send_search_entry( be, ps_conn, ps_op, e, attrs, attrsonly, ctrls );
if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL )
ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
ch_free( ctrls[--num_ctrls] );
ctrls[num_ctrls] = NULL;
} else
#endif
#ifdef LDAP_SYNC
if ( protocol == LDAP_SYNC ) {
rc = bdb_build_sync_state_ctrl( ps_conn, ps_op, e, entry_sync_state, ctrls,
num_ctrls++, 1, &latest_entrycsn_bv );
if ( rc != LDAP_SUCCESS )
goto done;
result = send_search_entry( be, ps_conn, ps_op, e, attrs, attrsonly, ctrls );
if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL )
ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
ch_free( ctrls[--num_ctrls] );
ctrls[num_ctrls] = NULL;
} else
#endif
{
rc = 1;
goto done;
}
} else if ( psearch_type == LDAP_PSEARCH_BY_PREMODIFY ) {
struct psid_entry* psid_e;
psid_e = (struct psid_entry *) calloc (1,
sizeof(struct psid_entry));
@ -844,9 +886,10 @@ done:
if( v2refs ) ber_bvarray_free( v2refs );
if( realbase.bv_val ) ch_free( realbase.bv_val );
if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
#ifdef LDAP_CLIENT_UPDATE
if ( IS_BDB_LCUP_REPLACE )
ch_free( attrs[0].an_name.bv_val );
#endif
return rc;
}
@ -1034,4 +1077,4 @@ static int psearch_candidates(
}
#endif /* LDAP_CLIENT_UPDATE */
#endif

View File

@ -277,7 +277,7 @@ bdb_modify(
int noop = 0;
#ifdef LDAP_CLIENT_UPDATE
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
Operation* ps_list;
struct psid_entry* pm_list;
struct psid_entry* pm_prev;
@ -302,7 +302,7 @@ retry: /* transaction retry */
"bdb_modify: retrying...\n", 0, 0, 0);
#endif
#ifdef LDAP_CLIENT_UPDATE
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
pm_list = LDAP_LIST_FIRST(&op->premodify_list);
while ( pm_list != NULL ) {
LDAP_LIST_REMOVE ( pm_list, link );
@ -423,13 +423,13 @@ retry: /* transaction retry */
goto done;
}
#ifdef LDAP_CLIENT_UPDATE
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
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 );
bdb_psearch(be, conn, op, ps_list, e, LDAP_PSEARCH_BY_PREMODIFY );
}
}
#endif /* LDAP_CLIENT_UPDATE */
#endif
/* Modify the entry */
rc = bdb_modify_internal( be, conn, op, ltid, modlist, e,
@ -518,23 +518,23 @@ return_results:
send_ldap_result( conn, op, rc,
NULL, text, NULL, NULL );
#ifdef LDAP_CLIENT_UPDATE
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
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 );
bdb_psearch( be, conn, op, ps_list, e, LDAP_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);
e, LDAP_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 */
#endif
if( rc == LDAP_SUCCESS && bdb->bi_txn_cp ) {
ldap_pvt_thread_yield();
@ -544,7 +544,7 @@ return_results:
done:
if( ltid != NULL ) {
#ifdef LDAP_CLIENT_UPDATE
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
pm_list = LDAP_LIST_FIRST(&op->premodify_list);
while ( pm_list != NULL ) {
LDAP_LIST_REMOVE ( pm_list, link );

View File

@ -62,7 +62,7 @@ bdb_modrdn(
int noop = 0;
#ifdef LDAP_CLIENT_UPDATE
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
Operation* ps_list;
struct psid_entry* pm_list;
struct psid_entry* pm_prev;
@ -95,7 +95,7 @@ retry: /* transaction retry */
Debug( LDAP_DEBUG_TRACE, "==>bdb_modrdn: retrying...\n", 0, 0, 0 );
#endif
#ifdef LDAP_CLIENT_UPDATE
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
pm_list = LDAP_LIST_FIRST(&op->premodify_list);
while ( pm_list != NULL ) {
LDAP_LIST_REMOVE ( pm_list, link );
@ -731,13 +731,13 @@ retry: /* transaction retry */
goto return_results;
}
#ifdef LDAP_CLIENT_UPDATE
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
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 );
bdb_psearch(be, conn, op, ps_list, e, LDAP_PSEARCH_BY_PREMODIFY );
}
}
#endif /* LDAP_CLIENT_UPDATE */
#endif
/* modify entry */
rc = bdb_modify_internal( be, conn, op, ltid, &mod[0], e,
@ -833,23 +833,23 @@ return_results:
send_ldap_result( conn, op, rc,
NULL, text, NULL, NULL );
#ifdef LDAP_CLIENT_UPDATE
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
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 );
bdb_psearch( be, conn, op, ps_list, e, LDAP_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);
e, LDAP_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 */
#endif
if( rc == LDAP_SUCCESS && bdb->bi_txn_cp ) {
ldap_pvt_thread_yield();
@ -893,7 +893,7 @@ done:
}
if( ltid != NULL ) {
#ifdef LDAP_CLIENT_UPDATE
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
pm_list = LDAP_LIST_FIRST(&op->premodify_list);
while ( pm_list != NULL ) {
LDAP_LIST_REMOVE ( pm_list, link );

View File

@ -364,13 +364,19 @@ int bdb_cache_delete_entry(
);
void bdb_cache_release_all( Cache *cache );
/*
* lcup.c
*/
#ifdef LDAP_CLIENT_UPDATE
int bdb_abandon(
BackendDB *be,
Connection *conn,
ber_int_t id
);
#endif
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
int bdb_add_psearch_spec(
BackendDB *be,
Connection *conn,
@ -384,7 +390,8 @@ int bdb_add_psearch_spec(
Filter *filter,
struct berval *fstr,
AttributeName *attrs,
int attrsonly
int attrsonly,
int protocol
);
int bdb_psearch(
@ -395,7 +402,66 @@ int bdb_psearch(
Entry *entry,
int psearch_type
);
#endif
/*
* search.c
*/
#ifdef LDAP_CLIENT_UPDATE
int
bdb_build_lcup_update_ctrl(
Connection *conn,
Operation *op,
Entry *e,
int entry_count,
LDAPControl **ctrls,
int num_ctrls,
struct berval *latest_entrycsn_bv,
int isdeleted );
int
bdb_build_lcup_done_ctrl(
Connection *conn,
Operation *op,
LDAPControl **ctrls,
int num_ctrls,
struct berval *latest_entrycsn_bv );
#endif
#ifdef LDAP_SYNC
int
bdb_build_sync_state_ctrl(
Connection *conn,
Operation *op,
Entry *e,
int entry_sync_state,
LDAPControl **ctrls,
int num_ctrls,
int send_cookie,
struct berval *latest_entrycsn_bv );
int
bdb_build_sync_done_ctrl(
Connection *conn,
Operation *op,
LDAPControl **ctrls,
int num_ctrls,
int send_cookie,
struct berval *latest_entrycsn_bv );
int
bdb_send_ldap_intermediate(
Connection *conn,
Operation *op,
ber_int_t err,
const char *matched,
const char *text,
BerVarray refs,
const char *rspoid,
int state,
struct berval *cookie,
LDAPControl **ctrls );
#endif
#ifdef BDB_REUSE_LOCKERS

View File

@ -65,13 +65,20 @@ bdb_search(
int tentries = 0;
ID lastid = NOID;
#ifdef LDAP_CLIENT_UPDATE
Filter lcupf, csnfnot, csnfeq, csnfand, csnfge;
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
Filter cookief, csnfnot, csnfeq, csnfand, csnfge;
AttributeAssertion aa_ge, aa_eq;
int entry_count = 0;
struct berval entrycsn_bv = { 0, NULL };
struct berval latest_entrycsn_bv = { 0, NULL };
#endif /* LDAP_CLIENT_UPDATE */
struct berval latest_entrycsn_bv = { 0, NULL };
LDAPControl *ctrls[SLAP_SEARCH_MAX_CTRLS];
int num_ctrls = 0;
#endif
#ifdef LDAP_SYNC
int rc_sync = 0;
int entry_sync_state;
AttributeName null_attr;
#endif
struct slap_limits_set *limit = NULL;
int isroot = 0;
@ -88,11 +95,32 @@ bdb_search(
#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 );
bdb_add_psearch_spec( be, conn, op, base, base, scope, deref, slimit,
tlimit, filter, filterstr, attrs, attrsonly, LDAP_CLIENT_UPDATE );
return LDAP_SUCCESS;
}
#endif
#if defined(LDAP_CLIENT_UPDATE) && defined(LDAP_SYNC)
else
#endif
#ifdef LDAP_SYNC
/* psearch needs to be registered before refresh begins */
/* psearch and refresh transmission is serialized in send_ldap_ber() */
if ( op->o_sync_mode & SLAP_SYNC_PERSIST ) {
bdb_add_psearch_spec( be, conn, op, base, base, scope, deref, slimit,
tlimit, filter, filterstr, attrs, attrsonly, LDAP_SYNC );
}
null_attr.an_desc = NULL;
null_attr.an_oc = NULL;
null_attr.an_name.bv_len = 0;
null_attr.an_name.bv_val = NULL;
#endif
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
for ( num_ctrls = 0; num_ctrls < SLAP_SEARCH_MAX_CTRLS; num_ctrls++ )
ctrls[num_ctrls] = NULL;
num_ctrls = 0;
#endif
manageDSAit = get_manageDSAit( op );
@ -394,9 +422,9 @@ dn2entry_retry:
#ifdef LDAP_CLIENT_UPDATE
if ( op->o_clientupdate_type & SLAP_LCUP_SYNC ) {
lcupf.f_choice = LDAP_FILTER_AND;
lcupf.f_and = &csnfnot;
lcupf.f_next = NULL;
cookief.f_choice = LDAP_FILTER_AND;
cookief.f_and = &csnfnot;
cookief.f_next = NULL;
csnfnot.f_choice = LDAP_FILTER_NOT;
csnfnot.f_not = &csnfeq;
@ -417,7 +445,36 @@ dn2entry_retry:
ber_dupbv( &csnfge.f_av_value, &op->o_clientupdate_state );
csnfge.f_next = filter;
}
#endif /* LDAP_CLIENT_UPDATE */
#endif
#if defined(LDAP_CLIENT_UPDATE) && defined(LDAP_SYNC)
else
#endif
#ifdef LDAP_SYNC
if ( op->o_sync_mode & SLAP_SYNC_REFRESH ) {
cookief.f_choice = LDAP_FILTER_AND;
cookief.f_and = &csnfnot;
cookief.f_next = NULL;
csnfnot.f_choice = LDAP_FILTER_NOT;
csnfnot.f_not = &csnfeq;
csnfnot.f_next = &csnfand;
csnfeq.f_choice = LDAP_FILTER_EQUALITY;
csnfeq.f_ava = &aa_eq;
csnfeq.f_av_desc = slap_schema.si_ad_entryCSN;
ber_dupbv( &csnfeq.f_av_value, &op->o_sync_state );
csnfand.f_choice = LDAP_FILTER_AND;
csnfand.f_and = &csnfge;
csnfand.f_next = NULL;
csnfge.f_choice = LDAP_FILTER_GE;
csnfge.f_ava = &aa_ge;
csnfge.f_av_desc = slap_schema.si_ad_entryCSN;
ber_dupbv( &csnfge.f_av_value, &op->o_sync_state );
csnfge.f_next = filter;
}
#endif
for ( id = bdb_idl_first( candidates, &cursor );
id != NOID;
@ -601,9 +658,22 @@ id2entry_retry:
/* if it matches the filter and scope, send it */
#ifdef LDAP_CLIENT_UPDATE
if ( op->o_clientupdate_type & SLAP_LCUP_SYNC ) {
rc = test_filter( be, conn, op, e, &lcupf );
rc = test_filter( be, conn, op, e, &cookief );
} else
#endif /* LDAP_CLIENT_UPDATE */
#endif
#ifdef LDAP_SYNC
if ( op->o_sync_mode & SLAP_SYNC_REFRESH ) {
rc_sync = test_filter( be, conn, op, e, &cookief );
rc = test_filter( be, conn, op, e, filter );
if ( rc == LDAP_COMPARE_TRUE ) {
if ( rc_sync == LDAP_COMPARE_TRUE ) {
entry_sync_state = LDAP_SYNC_ADD;
} else {
entry_sync_state = LDAP_SYNC_PRESENT;
}
}
} else
#endif
{
rc = test_filter( be, conn, op, e, filter );
}
@ -658,100 +728,41 @@ id2entry_retry:
{
#ifdef LDAP_CLIENT_UPDATE
if ( op->o_clientupdate_type & SLAP_LCUP_SYNC ) {
Attribute* a;
int ret;
int res;
const char *text = NULL;
LDAPControl *ctrls[2];
char berbuf[LBER_ELEMENT_SIZEOF];
BerElement *ber = (BerElement *)berbuf;
ber_init2( ber, 0, LBER_USE_DER );
entry_count++;
ctrls[0] = ch_malloc ( sizeof ( LDAPControl ) );
ctrls[1] = NULL;
if ( entry_count % op->o_clientupdate_interval == 0 ) {
/* Send cookie */
for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
AttributeDescription *desc = a->a_desc;
if ( desc == slap_schema.si_ad_entryCSN ) {
ber_dupbv( &entrycsn_bv, &a->a_vals[0] );
if ( latest_entrycsn_bv.bv_val == NULL ) {
ber_dupbv( &latest_entrycsn_bv, &entrycsn_bv );
} else {
res = value_match( &ret, desc,
desc->ad_type->sat_ordering,
SLAP_MR_ASSERTION_SYNTAX_MATCH,
&entrycsn_bv, &latest_entrycsn_bv, &text );
if ( res != LDAP_SUCCESS ) {
ret = 0;
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, RESULTS,
"bdb_search: value_match failed\n",
0, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"bdb_search: value_match failed\n",
0, 0, 0 );
#endif
}
if ( ret > 0 ) {
ch_free( latest_entrycsn_bv.bv_val );
latest_entrycsn_bv.bv_val = NULL;
ber_dupbv( &latest_entrycsn_bv,
&entrycsn_bv );
}
}
}
}
ber_printf( ber,
"{bb{sON}N}",
SLAP_LCUP_STATE_UPDATE_FALSE,
SLAP_LCUP_ENTRY_DELETED_FALSE,
LCUP_COOKIE_OID, &entrycsn_bv );
ch_free( entrycsn_bv.bv_val );
entrycsn_bv.bv_val = NULL;
} else {
/* Do not send cookie */
ber_printf( ber,
"{bbN}",
SLAP_LCUP_STATE_UPDATE_FALSE,
SLAP_LCUP_ENTRY_DELETED_FALSE );
}
ctrls[0]->ldctl_oid = LDAP_CONTROL_ENTRY_UPDATE;
ctrls[0]->ldctl_iscritical = op->o_clientupdate;
ret = ber_flatten2( ber, &ctrls[0]->ldctl_value, 0 );
if ( ret < 0 ) {
ber_free_buf( ber );
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, RESULTS,
"bdb_search: ber_flatten2 failed\n",
0, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"bdb_search: ber_flatten2 failed\n",
0, 0, 0 );
#endif
send_ldap_result( conn, op, rc=LDAP_OTHER,
NULL, "internal error", NULL, NULL );
rc = bdb_build_lcup_update_ctrl( conn, op, e, ++entry_count, ctrls,
num_ctrls++, &latest_entrycsn_bv, SLAP_LCUP_ENTRY_DELETED_FALSE );
if ( rc != LDAP_SUCCESS )
goto done;
result = send_search_entry( be, conn, op,
e, attrs, attrsonly, ctrls);
if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL )
ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
ch_free( ctrls[--num_ctrls] );
ctrls[num_ctrls] = NULL;
} else
#endif
#ifdef LDAP_SYNC
if ( op->o_sync_mode & SLAP_SYNC_REFRESH ) {
rc = bdb_build_sync_state_ctrl( conn, op, e, entry_sync_state, ctrls,
num_ctrls++, 0, &latest_entrycsn_bv );
if ( rc != LDAP_SUCCESS )
goto done;
if ( rc_sync == LDAP_COMPARE_TRUE ) { /* ADD */
result = send_search_entry( be, conn, op,
e, attrs, attrsonly, ctrls);
} else { /* PRESENT */
result = send_search_entry( be, conn, op,
e, &null_attr, attrsonly, ctrls);
}
result = send_search_entry( be, conn, op,
e, attrs, attrsonly, ctrls);
ber_free_buf( ber );
ch_free( ctrls[0] );
if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL )
ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
ch_free( ctrls[--num_ctrls] );
ctrls[num_ctrls] = NULL;
} else
#endif /* LDAP_CLIENT_UPDATE */
#endif
{
result = send_search_entry( be, conn, op,
e, attrs, attrsonly, NULL);
@ -806,47 +817,44 @@ loop_continue:
#ifdef LDAP_CLIENT_UPDATE
if ( op->o_clientupdate_type & SLAP_LCUP_SYNC ) {
int ret;
LDAPControl *ctrls[2];
char berbuf[LBER_ELEMENT_SIZEOF];
BerElement *ber = (BerElement *)berbuf;
ber_init2( ber, NULL, LBER_USE_DER );
ctrls[0] = ch_malloc ( sizeof ( LDAPControl ) );
ctrls[1] = NULL;
ber_printf( ber, "{sO", LCUP_COOKIE_OID, &latest_entrycsn_bv );
ber_printf( ber, "N}" );
ctrls[0]->ldctl_oid = LDAP_CONTROL_CLIENT_UPDATE_DONE;
ctrls[0]->ldctl_iscritical = op->o_clientupdate;
ret = ber_flatten2( ber, &ctrls[0]->ldctl_value, 0 );
if ( ret < 0 ) {
ber_free_buf( ber );
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, RESULTS,
"bdb_search: ber_flatten2 failed\n", 0, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE, "bdb_search: ber_flatten2 failed\n",
0, 0, 0 );
#endif
send_ldap_result( conn, op, rc=LDAP_OTHER,
NULL, "internal error", NULL, NULL );
goto done;
}
bdb_build_lcup_done_ctrl( conn, op, ctrls, num_ctrls++, &latest_entrycsn_bv );
send_search_result( conn, op,
v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
NULL, NULL, v2refs, ctrls, nentries );
v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
NULL, NULL, v2refs, ctrls, nentries );
ch_free( latest_entrycsn_bv.bv_val );
latest_entrycsn_bv.bv_val = NULL;
ch_free( ctrls[0] );
ber_free_buf( ber );
if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL )
ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
ch_free( ctrls[--num_ctrls] );
ctrls[num_ctrls] = NULL;
} else
#endif /* LDAP_CLIENT_UPDATE */
#endif
#ifdef LDAP_SYNC
if ( op->o_sync_mode & SLAP_SYNC_REFRESH ) {
if ( op->o_sync_mode & SLAP_SYNC_PERSIST ) {
/* refreshAndPersist mode */
bdb_send_ldap_intermediate( conn, op,
LDAP_SUCCESS, NULL, NULL, NULL, LDAP_SYNC_INFO,
LDAP_SYNC_REFRESH_DONE, &latest_entrycsn_bv, NULL );
} else {
/* refreshOnly mode */
bdb_build_sync_done_ctrl( conn, op, ctrls, num_ctrls++, 1, &latest_entrycsn_bv );
send_search_result( conn, op,
v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
NULL, NULL, v2refs, ctrls, nentries );
if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL )
ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
ch_free( ctrls[--num_ctrls] );
ctrls[num_ctrls] = NULL;
}
ch_free( latest_entrycsn_bv.bv_val );
latest_entrycsn_bv.bv_val = NULL;
} else
#endif
{
send_search_result( conn, op,
v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
@ -871,7 +879,21 @@ done:
ch_free( csnfge.f_av_value.bv_val );
}
}
#endif /* LDAP_CLIENT_UPDATE */
#endif
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
else
#endif
#ifdef LDAP_SYNC
if ( op->o_sync_mode & SLAP_SYNC_REFRESH ) {
if ( csnfeq.f_ava != NULL && csnfeq.f_av_value.bv_val != NULL ) {
ch_free( csnfeq.f_av_value.bv_val );
}
if ( csnfge.f_ava != NULL && csnfge.f_av_value.bv_val != NULL ) {
ch_free( csnfge.f_av_value.bv_val );
}
}
#endif
LOCK_ID_FREE (bdb->bi_dbenv, locker );
@ -1159,3 +1181,333 @@ done:
(void) ber_free_buf( ber );
}
#ifdef LDAP_CLIENT_UPDATE
int
bdb_build_lcup_update_ctrl(
Connection *conn,
Operation *op,
Entry *e,
int entry_count,
LDAPControl **ctrls,
int num_ctrls,
struct berval *latest_entrycsn_bv,
int isdeleted )
{
Attribute* a;
int ret;
int res;
int rc;
const char *text = NULL;
char berbuf[LBER_ELEMENT_SIZEOF];
BerElement *ber = (BerElement *)berbuf;
struct berval entrycsn_bv = { 0, NULL };
ber_init2( ber, 0, LBER_USE_DER );
ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
AttributeDescription *desc = a->a_desc;
if ( desc == slap_schema.si_ad_entryCSN ) {
ber_dupbv( &entrycsn_bv, &a->a_vals[0] );
if ( latest_entrycsn_bv->bv_val == NULL ) {
ber_dupbv( latest_entrycsn_bv, &entrycsn_bv );
} else {
res = value_match( &ret, desc,
desc->ad_type->sat_ordering,
SLAP_MR_ASSERTION_SYNTAX_MATCH,
&entrycsn_bv, latest_entrycsn_bv, &text );
if ( res != LDAP_SUCCESS ) {
ret = 0;
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, RESULTS,
"bdb_search: value_match failed\n",
0, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"bdb_search: value_match failed\n",
0, 0, 0 );
#endif
}
if ( ret > 0 ) {
ch_free( latest_entrycsn_bv->bv_val );
latest_entrycsn_bv->bv_val = NULL;
ber_dupbv( latest_entrycsn_bv, &entrycsn_bv );
}
}
}
}
if ( entry_count % op->o_clientupdate_interval == 0 )
ber_printf( ber,
"{bb{sON}N}",
SLAP_LCUP_STATE_UPDATE_FALSE,
isdeleted,
LDAP_LCUP_COOKIE_OID, &entrycsn_bv );
else /* Do not send cookie */
ber_printf( ber,
"{bbN}",
SLAP_LCUP_STATE_UPDATE_FALSE,
isdeleted );
ch_free( entrycsn_bv.bv_val );
entrycsn_bv.bv_val = NULL;
ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_ENTRY_UPDATE;
ctrls[num_ctrls]->ldctl_iscritical = op->o_clientupdate;
ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
ber_free_buf( ber );
if ( ret < 0 ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, RESULTS,
"bdb_build_lcup_ctrl: ber_flatten2 failed\n",
0, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"bdb_build_lcup_ctrl: ber_flatten2 failed\n",
0, 0, 0 );
#endif
send_ldap_result( conn, op, rc=LDAP_OTHER,
NULL, "internal error", NULL, NULL );
return ret;
}
return LDAP_SUCCESS;
}
int
bdb_build_lcup_done_ctrl(
Connection *conn,
Operation *op,
LDAPControl **ctrls,
int num_ctrls,
struct berval *latest_entrycsn_bv )
{
int ret, rc;
char berbuf[LBER_ELEMENT_SIZEOF];
BerElement *ber = (BerElement *)berbuf;
ber_init2( ber, NULL, LBER_USE_DER );
ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
ber_printf( ber, "{sO", LDAP_LCUP_COOKIE_OID, latest_entrycsn_bv );
ber_printf( ber, "N}" );
ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_CLIENT_UPDATE_DONE;
ctrls[num_ctrls]->ldctl_iscritical = op->o_clientupdate;
ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
ber_free_buf( ber );
if ( ret < 0 ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, RESULTS,
"bdb_build_lcup_done_ctrl: ber_flatten2 failed\n", 0, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE, "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n",
0, 0, 0 );
#endif
send_ldap_result( conn, op, rc=LDAP_OTHER,
NULL, "internal error", NULL, NULL );
return ret;
}
return LDAP_SUCCESS;
}
#endif
#ifdef LDAP_SYNC
int
bdb_build_sync_state_ctrl(
Connection *conn,
Operation *op,
Entry *e,
int entry_sync_state,
LDAPControl **ctrls,
int num_ctrls,
int send_cookie,
struct berval *latest_entrycsn_bv )
{
Attribute* a;
int ret;
int res;
int rc;
const char *text = NULL;
char berbuf[LBER_ELEMENT_SIZEOF];
BerElement *ber = (BerElement *)berbuf;
struct berval entryuuid_bv = { 0, NULL };
struct berval entrycsn_bv = { 0, NULL };
ber_init2( ber, 0, LBER_USE_DER );
ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
AttributeDescription *desc = a->a_desc;
if ( desc == slap_schema.si_ad_entryCSN ) {
ber_dupbv( &entrycsn_bv, &a->a_vals[0] );
if ( latest_entrycsn_bv->bv_val == NULL ) {
ber_dupbv( latest_entrycsn_bv, &entrycsn_bv );
} else {
res = value_match( &ret, desc,
desc->ad_type->sat_ordering,
SLAP_MR_ASSERTION_SYNTAX_MATCH,
&entrycsn_bv, latest_entrycsn_bv, &text );
if ( res != LDAP_SUCCESS ) {
ret = 0;
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, RESULTS,
"bdb_search: value_match failed\n",
0, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"bdb_search: value_match failed\n",
0, 0, 0 );
#endif
}
if ( ret > 0 ) {
ch_free( latest_entrycsn_bv->bv_val );
latest_entrycsn_bv->bv_val = NULL;
ber_dupbv( latest_entrycsn_bv, &entrycsn_bv );
}
}
} else if ( desc == slap_schema.si_ad_entryUUID ) {
ber_dupbv( &entryuuid_bv, &a->a_vals[0] );
}
}
if ( send_cookie )
ber_printf( ber, "{eOON}", entry_sync_state, &entryuuid_bv, &entrycsn_bv );
else
ber_printf( ber, "{eON}", entry_sync_state, &entryuuid_bv );
ch_free( entrycsn_bv.bv_val );
entrycsn_bv.bv_val = NULL;
ch_free( entryuuid_bv.bv_val );
entryuuid_bv.bv_val = NULL;
ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_SYNC_STATE;
ctrls[num_ctrls]->ldctl_iscritical = op->o_sync;
ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
ber_free_buf( ber );
if ( ret < 0 ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, RESULTS,
"bdb_build_sync_ctrl: ber_flatten2 failed\n",
0, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"bdb_build_sync_ctrl: ber_flatten2 failed\n",
0, 0, 0 );
#endif
send_ldap_result( conn, op, rc=LDAP_OTHER,
NULL, "internal error", NULL, NULL );
return ret;
}
return LDAP_SUCCESS;
}
int
bdb_build_sync_done_ctrl(
Connection *conn,
Operation *op,
LDAPControl **ctrls,
int num_ctrls,
int send_cookie,
struct berval *latest_entrycsn_bv )
{
int ret,rc;
char berbuf[LBER_ELEMENT_SIZEOF];
BerElement *ber = (BerElement *)berbuf;
ber_init2( ber, NULL, LBER_USE_DER );
ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
if ( send_cookie ) {
ber_printf( ber, "{ON}", latest_entrycsn_bv );
} else {
ber_printf( ber, "{N}" );
}
ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_SYNC_DONE;
ctrls[num_ctrls]->ldctl_iscritical = op->o_sync;
ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
ber_free_buf( ber );
if ( ret < 0 ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, RESULTS,
"bdb_build_lcup_done_ctrl: ber_flatten2 failed\n", 0, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE, "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n",
0, 0, 0 );
#endif
send_ldap_result( conn, op, rc=LDAP_OTHER,
NULL, "internal error", NULL, NULL );
return ret;
}
return LDAP_SUCCESS;
}
int
bdb_send_ldap_intermediate(
Connection *conn,
Operation *op,
ber_int_t err,
const char *matched,
const char *text,
BerVarray refs,
const char *rspoid,
int state,
struct berval *cookie,
LDAPControl **ctrls )
{
char berbuf[LBER_ELEMENT_SIZEOF];
BerElement *ber = (BerElement *)berbuf;
struct berval rspdata;
int ret, rc;
ber_init2( ber, NULL, LBER_USE_DER );
if ( cookie == NULL )
ber_printf( ber, "{eN}", state );
else
ber_printf( ber, "{eON}", state, cookie );
ret = ber_flatten2( ber, &rspdata, 0 );
if ( ret < 0 ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, RESULTS,
"bdb_build_lcup_done_ctrl: ber_flatten2 failed\n", 0, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE, "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n",
0, 0, 0 );
#endif
send_ldap_result( conn, op, rc=LDAP_OTHER,
NULL, "internal error", NULL, NULL );
return ret;
}
send_ldap_intermediate_resp( conn, op, err, matched, text, refs, rspoid, &rspdata, ctrls );
ber_free_buf( ber );
return LDAP_SUCCESS;
}
#endif

View File

@ -35,6 +35,7 @@ int cancel_extop(
int found = 0;
int opid;
BerElement *ber;
int i;
assert( reqoid != NULL );
assert( strcmp( LDAP_EXOP_X_CANCEL, reqoid ) == 0 );
@ -86,9 +87,22 @@ int cancel_extop(
}
if ( !found ) {
#ifdef LDAP_SYNC
for ( i = 0; i < nbackends; i++ ) {
if ( strncmp( backends[i].be_type, "bdb", 3 ) ) continue;
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
if ( bdb_cancel( &backends[i], conn, opid ) == LDAP_SUCCESS ) {
return LDAP_SUCCESS;
} else {
*text = "message ID not found";
return LDAP_NO_SUCH_OPERATION;
}
}
#else
*text = "message ID not found";
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
return LDAP_NO_SUCH_OPERATION;
return LDAP_NO_SUCH_OPERATION;
#endif
}
if ( op->o_cancel != LDAP_CANCEL_NONE ) {
@ -114,3 +128,4 @@ int cancel_extop(
return rc;
}

View File

@ -1040,12 +1040,26 @@ operations_error:
LDAP_STAILQ_REMOVE( &conn->c_ops, arg->co_op, slap_op, o_next);
LDAP_STAILQ_NEXT(arg->co_op, o_next) = NULL;
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
if ( arg->co_op->o_cancel == LDAP_CANCEL_ACK )
goto co_op_free;
#endif
#ifdef LDAP_CLIENT_UPDATE
if ( !( arg->co_op->o_clientupdate_type & SLAP_LCUP_PERSIST ) )
#endif /* LDAP_CLIENT_UPDATE */
{
slap_op_free( arg->co_op );
}
if ( ( arg->co_op->o_clientupdate_type & SLAP_LCUP_PERSIST ) )
goto no_co_op_free;
#endif
#ifdef LDAP_SYNC
if ( ( arg->co_op->o_sync_mode & SLAP_SYNC_PERSIST ) )
goto no_co_op_free;
#endif
co_op_free:
slap_op_free( arg->co_op );
no_co_op_free:
arg->co_op = NULL;
arg->co_conn = NULL;
free( (char *) arg );

View File

@ -58,6 +58,9 @@ static SLAP_CTRL_PARSE_FN parseSubentries;
#ifdef LDAP_CLIENT_UPDATE
static SLAP_CTRL_PARSE_FN parseClientUpdate;
#endif
#ifdef LDAP_SYNC
static SLAP_CTRL_PARSE_FN parseLdupSync;
#endif
#undef sc_mask /* avoid conflict with Irix 6.5 <sys/signal.h> */
@ -108,7 +111,12 @@ static struct slap_control {
{ LDAP_CONTROL_CLIENT_UPDATE,
SLAP_CTRL_SEARCH, NULL,
parseClientUpdate },
#endif /* LDAP_CLIENT_UPDATE */
#endif
#ifdef LDAP_SYNC
{ LDAP_CONTROL_SYNC,
SLAP_CTRL_SEARCH, NULL,
parseLdupSync },
#endif
{ NULL, 0, NULL, 0 }
};
@ -829,6 +837,13 @@ static int parseClientUpdate (
return LDAP_PROTOCOL_ERROR;
}
#ifdef LDAP_SYNC
if ( op->o_sync != SLAP_NO_CONTROL ) {
*text = "LDAP Client Update and Sync controls used together";
return LDAP_PROTOCOL_ERROR;
}
#endif
if ( ctrl->ldctl_value.bv_len == 0 ) {
*text = "LCUP client update control value is empty (or absent)";
return LDAP_PROTOCOL_ERROR;
@ -897,7 +912,7 @@ static int parseClientUpdate (
return LDAP_PROTOCOL_ERROR;
}
if ( tag == LDAP_TAG_COOKIE ) {
if ( tag == LDAP_LCUP_TAG_COOKIE ) {
if ( (tag = ber_scanf( ber, /*{*/ "{mm}}",
&scheme, &cookie )) == LBER_ERROR ) {
*text = "LCUP client update control : decoding error";
@ -931,4 +946,113 @@ static int parseClientUpdate (
return LDAP_SUCCESS;
}
#endif /* LDAP_CLIENT_UPDATE */
#endif
#ifdef LDAP_SYNC
static int parseLdupSync (
Connection *conn,
Operation *op,
LDAPControl *ctrl,
const char **text )
{
ber_tag_t tag;
BerElement *ber;
ber_int_t mode;
ber_len_t len;
struct berval cookie = { 0, NULL };
if ( op->o_sync != SLAP_NO_CONTROL ) {
*text = "LDAP Sync control specified multiple times";
return LDAP_PROTOCOL_ERROR;
}
#ifdef LDAP_CLIENT_UPDATE
if ( op->o_clientupdate != SLAP_NO_CONTROL ) {
*text = "LDAP Sync and LDAP Client Update controls used together";
return LDAP_PROTOCOL_ERROR;
}
#endif
if ( ctrl->ldctl_value.bv_len == 0 ) {
*text = "LDAP Sync control value is empty (or absent)";
return LDAP_PROTOCOL_ERROR;
}
/* Parse the control value
* syncRequestValue ::= SEQUENCE {
* mode ENUMERATED {
* -- 0 unused
* refreshOnly (1),
* -- 2 reserved
* refreshAndPersist (3)
* },
* cookie syncCookie OPTIONAL
* }
*/
ber = ber_init( &ctrl->ldctl_value );
if( ber == NULL ) {
*text = "internal error";
return LDAP_OTHER;
}
if ( (tag = ber_scanf( ber, "{i" /*}*/, &mode )) == LBER_ERROR ) {
*text = "LDAP Sync control : mode decoding error";
return LDAP_PROTOCOL_ERROR;
}
switch( mode ) {
case LDAP_SYNC_REFRESH_ONLY:
mode = SLAP_SYNC_REFRESH;
break;
case LDAP_SYNC_REFRESH_AND_PERSIST:
mode = SLAP_SYNC_REFRESH_AND_PERSIST;
break;
default:
*text = "LDAP Sync control : unknown update mode";
return LDAP_PROTOCOL_ERROR;
}
tag = ber_peek_tag( ber, &len );
if ( tag == LDAP_SYNC_TAG_COOKIE ) {
if (( ber_scanf( ber, /*{*/ "m}",
&cookie )) == LBER_ERROR ) {
*text = "LDAP Sync control : cookie decoding error";
return LDAP_PROTOCOL_ERROR;
}
} else {
if (( ber_scanf( ber, /*{*/ "}")) == LBER_ERROR ) {
*text = "LDAP Sync control : decoding error";
return LDAP_PROTOCOL_ERROR;
}
cookie.bv_len = 0;
cookie.bv_val = NULL;
}
/* TODO : Cookie Scheme Validation */
#if 0
if ( lcup_cookie_scheme_validate(scheme) != LDAP_SUCCESS ) {
*text = "Unsupported LCUP cookie scheme";
return LCUP_UNSUPPORTED_SCHEME;
}
if ( lcup_cookie_validate(scheme, cookie) != LDAP_SUCCESS ) {
*text = "Invalid LCUP cookie";
return LCUP_INVALID_COOKIE;
}
#endif
ber_dupbv( &op->o_sync_state, &cookie );
(void) ber_free( ber, 1 );
op->o_sync_mode = (char) mode;
op->o_sync = ctrl->ldctl_iscritical
? SLAP_CRITICAL_CONTROL
: SLAP_NONCRITICAL_CONTROL;
return LDAP_SUCCESS;
}
#endif

View File

@ -46,7 +46,12 @@ slap_op_free( Operation *op )
if ( op->o_clientupdate_state.bv_val != NULL ) {
free( op->o_clientupdate_state.bv_val );
}
#endif /* LDAP_CLIENT_UPDATE */
#endif
#ifdef LDAP_SYNC
if ( op->o_sync_state.bv_val != NULL ) {
free( op->o_sync_state.bv_val );
}
#endif
#if defined( LDAP_SLAPI )
if ( op->o_pb != NULL ) {

View File

@ -415,20 +415,28 @@ do_search(
#endif /* LDAP_SLAPI */
return_results:;
#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 );
#ifdef LDAP_CLIENT_UPDATE
if ( ( op->o_clientupdate_type & SLAP_LCUP_PERSIST ) )
return rc;
#endif
#if defined(LDAP_CLIENT_UPDATE) && defined(LDAP_SYNC)
else
#endif
#ifdef LDAP_SYNC
if ( ( op->o_sync_mode & SLAP_SYNC_PERSIST ) )
return rc;
#endif
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 );
#ifdef LDAP_SLAPI
if( attrs != NULL) ch_free( attrs );
if( attrs != NULL) ch_free( attrs );
#endif /* LDAP_SLAPI */
}
return rc;
}

View File

@ -1615,14 +1615,14 @@ typedef struct slap_paged_state {
} 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
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
#define LDAP_PSEARCH_BY_ADD 0x01
#define LDAP_PSEARCH_BY_DELETE 0x02
#define LDAP_PSEARCH_BY_PREMODIFY 0x03
#define LDAP_PSEARCH_BY_MODIFY 0x04
#define LDAP_PSEARCH_BY_SCOPEOUT 0x05
struct lcup_search_spec {
struct ldap_psearch_spec {
struct slap_op *op;
struct berval *base;
struct berval *nbase;
@ -1634,17 +1634,16 @@ struct lcup_search_spec {
struct berval *filterstr;
AttributeName *attrs;
int attrsonly;
struct lcup_entry *elist;
ldap_pvt_thread_mutex_t elist_mutex;
int protocol;
int entry_count;
LDAP_LIST_ENTRY(lcup_search_spec) link;
LDAP_LIST_ENTRY(ldap_psearch_spec) link;
};
struct psid_entry {
struct lcup_search_spec* ps;
struct ldap_psearch_spec* ps;
LDAP_LIST_ENTRY(psid_entry) link;
};
#endif /* LDAP_CLIENT_UPDATE */
#endif
/*
@ -1691,13 +1690,26 @@ typedef struct slap_op {
#define SLAP_LCUP_NONE (0x0)
#define SLAP_LCUP_SYNC (0x1)
#define SLAP_LCUP_PERSIST (0x2)
#define SLAP_LCUP_SYNC_AND_PERSIST (0x3)
#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;
#endif
#ifdef LDAP_SYNC
char o_sync;
char o_sync_mode;
#define SLAP_SYNC_NONE (0x0)
#define SLAP_SYNC_REFRESH (0x1)
#define SLAP_SYNC_PERSIST (0x2)
#define SLAP_SYNC_REFRESH_AND_PERSIST (0x3)
struct berval o_sync_state;
#endif
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
LDAP_LIST_HEAD(lss, ldap_psearch_spec) psearch_spec;
LDAP_LIST_HEAD(pe, psid_entry) premodify_list;
LDAP_LIST_ENTRY(slap_op) link;
#endif /* LDAP_CLIENT_UPDATE */
#endif
#ifdef LDAP_CONNECTIONLESS
Sockaddr o_peeraddr; /* UDP peer address */
@ -1997,6 +2009,10 @@ enum {
#define SLAP_LCUP_ENTRY_DELETED_FALSE 0
#endif /* LDAP_CLIENT_UPDATE */
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
#define SLAP_SEARCH_MAX_CTRLS 10
#endif
LDAP_END_DECL
#include "proto-slap.h"