mirror of
https://git.openldap.org/openldap/openldap.git
synced 2026-01-08 08:02:16 -05:00
Preliminary multi-context support for syncrepl. Passes all single-master
tests, needs multi-master testing.
This commit is contained in:
parent
e0ed944be3
commit
fffaea79eb
7 changed files with 741 additions and 399 deletions
|
|
@ -555,7 +555,7 @@ static ConfigTable config_back_cf_table[] = {
|
|||
"SYNTAX OMsDN )", NULL, NULL },
|
||||
{ "syncrepl", NULL, 0, 0, 0, ARG_DB|ARG_MAGIC,
|
||||
&syncrepl_config, "( OLcfgDbAt:0.11 NAME 'olcSyncrepl' "
|
||||
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
|
||||
"SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
|
||||
{ "threads", "count", 2, 2, 0,
|
||||
#ifdef NO_THREADS
|
||||
ARG_IGNORED, NULL,
|
||||
|
|
@ -760,8 +760,6 @@ typedef struct ServerID {
|
|||
int si_num;
|
||||
} ServerID;
|
||||
|
||||
#define SERVERID_MAX 4095
|
||||
|
||||
static ServerID *sid_list;
|
||||
|
||||
static int
|
||||
|
|
@ -1574,7 +1572,7 @@ config_generic(ConfigArgs *c) {
|
|||
ServerID *si, **sip;
|
||||
LDAPURLDesc *lud;
|
||||
int num = atoi( c->argv[1] );
|
||||
if ( num < 0 || num > SERVERID_MAX ) {
|
||||
if ( num < 0 || num > SLAP_SYNC_SID_MAX ) {
|
||||
snprintf( c->msg, sizeof( c->msg ),
|
||||
"<%s> illegal server ID", c->argv[0] );
|
||||
Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
|
||||
|
|
@ -1636,7 +1634,7 @@ config_generic(ConfigArgs *c) {
|
|||
for ( i=0; l[i]; i++ ) {
|
||||
LDAPURLDesc *lu2;
|
||||
int isMe = 0;
|
||||
ldap_url_parse( &l[i]->sl_url, &lu2 );
|
||||
ldap_url_parse( l[i]->sl_url.bv_val, &lu2 );
|
||||
do {
|
||||
if ( strcasecmp( lud->lud_scheme,
|
||||
lu2->lud_scheme ))
|
||||
|
|
|
|||
|
|
@ -34,34 +34,47 @@ void
|
|||
slap_compose_sync_cookie(
|
||||
Operation *op,
|
||||
struct berval *cookie,
|
||||
struct berval *csn,
|
||||
BerVarray csn,
|
||||
int rid )
|
||||
{
|
||||
char cookiestr[ LDAP_LUTIL_CSNSTR_BUFSIZE + 20 ];
|
||||
int len;
|
||||
int len, numcsn = 0;
|
||||
|
||||
if ( BER_BVISNULL( csn )) {
|
||||
if ( csn ) {
|
||||
for (; !BER_BVISEMPTY( &csn[numcsn] ); numcsn++);
|
||||
}
|
||||
|
||||
if ( numcsn == 0 || rid == -1 ) {
|
||||
char cookiestr[ LDAP_LUTIL_CSNSTR_BUFSIZE + 20 ];
|
||||
if ( rid == -1 ) {
|
||||
cookiestr[0] = '\0';
|
||||
len = 0;
|
||||
} else {
|
||||
len = snprintf( cookiestr, LDAP_LUTIL_CSNSTR_BUFSIZE + 20,
|
||||
len = snprintf( cookiestr, sizeof( cookiestr ),
|
||||
"rid=%03d", rid );
|
||||
}
|
||||
ber_str2bv_x( cookiestr, len, 1, cookie,
|
||||
op ? op->o_tmpmemctx : NULL );
|
||||
} else {
|
||||
char *end = cookiestr + sizeof(cookiestr);
|
||||
char *ptr = lutil_strcopy( cookiestr, "csn=" );
|
||||
len = csn->bv_len;
|
||||
if ( ptr + len >= end )
|
||||
len = end - ptr;
|
||||
ptr = lutil_strncopy( ptr, csn->bv_val, len );
|
||||
if ( rid != -1 && ptr < end - STRLENOF(",rid=xxx") ) {
|
||||
ptr += sprintf( ptr, ",rid=%03d", rid );
|
||||
char *ptr;
|
||||
int i;
|
||||
|
||||
len = 0;
|
||||
for ( i=0; i<numcsn; i++)
|
||||
len += csn[i].bv_len + 1;
|
||||
|
||||
len += STRLENOF("rid=123,csn=");
|
||||
cookie->bv_val = slap_sl_malloc( len, op ? op->o_tmpmemctx : NULL );
|
||||
|
||||
len = sprintf( cookie->bv_val, "rid=%03d,csn=", rid );
|
||||
ptr = cookie->bv_val + len;
|
||||
for ( i=0; i<numcsn; i++) {
|
||||
ptr = lutil_strncopy( ptr, csn->bv_val, csn->bv_len );
|
||||
*ptr++ = ';';
|
||||
}
|
||||
len = ptr - cookiestr;
|
||||
ptr--;
|
||||
*ptr = '\0';
|
||||
cookie->bv_len = ptr - cookie->bv_val;
|
||||
}
|
||||
ber_str2bv_x( cookiestr, len, 1, cookie,
|
||||
op ? op->o_tmpmemctx : NULL );
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -73,11 +86,16 @@ slap_sync_cookie_free(
|
|||
if ( cookie == NULL )
|
||||
return;
|
||||
|
||||
if ( !BER_BVISNULL( &cookie->ctxcsn )) {
|
||||
ch_free( cookie->ctxcsn.bv_val );
|
||||
BER_BVZERO( &cookie->ctxcsn );
|
||||
if ( cookie->sids ) {
|
||||
ch_free( cookie->sids );
|
||||
cookie->sids = NULL;
|
||||
}
|
||||
|
||||
if ( cookie->ctxcsn ) {
|
||||
ber_bvarray_free( cookie->ctxcsn );
|
||||
cookie->ctxcsn = NULL;
|
||||
}
|
||||
cookie->numcsns = 0;
|
||||
if ( !BER_BVISNULL( &cookie->octet_str )) {
|
||||
ch_free( cookie->octet_str.bv_val );
|
||||
BER_BVZERO( &cookie->octet_str );
|
||||
|
|
@ -90,6 +108,37 @@ slap_sync_cookie_free(
|
|||
return;
|
||||
}
|
||||
|
||||
int
|
||||
slap_parse_csn_sid( struct berval *csn )
|
||||
{
|
||||
char *p, *q;
|
||||
int i;
|
||||
|
||||
p = memchr( csn->bv_val, '#', csn->bv_len );
|
||||
if ( p )
|
||||
p = strchr( p+1, '#' );
|
||||
if ( !p )
|
||||
return -1;
|
||||
p++;
|
||||
i = strtoul( p, &q, 10 );
|
||||
if ( p == q || i > SLAP_SYNC_SID_MAX )
|
||||
i = -1;
|
||||
return i;
|
||||
}
|
||||
|
||||
int *
|
||||
slap_parse_csn_sids( BerVarray csns, int numcsns )
|
||||
{
|
||||
int i, *ret;
|
||||
char *p, *q;
|
||||
|
||||
ret = ch_malloc( numcsns * sizeof(int) );
|
||||
for ( i=0; i<numcsns; i++ ) {
|
||||
ret[i] = slap_parse_csn_sid( &csns[i] );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
slap_parse_sync_cookie(
|
||||
struct sync_cookie *cookie,
|
||||
|
|
@ -99,10 +148,10 @@ slap_parse_sync_cookie(
|
|||
char *csn_ptr;
|
||||
char *csn_str;
|
||||
int csn_str_len;
|
||||
int valid = 0;
|
||||
char *rid_ptr;
|
||||
char *cval;
|
||||
char *next;
|
||||
char *next, *end;
|
||||
AttributeDescription *ad = slap_schema.si_ad_modifyTimestamp;
|
||||
|
||||
if ( cookie == NULL )
|
||||
return -1;
|
||||
|
|
@ -111,60 +160,76 @@ slap_parse_sync_cookie(
|
|||
return -1;
|
||||
|
||||
cookie->rid = -1;
|
||||
/* FIXME: may read past end of cookie->octet_str.bv_val */
|
||||
rid_ptr = strstr( cookie->octet_str.bv_val, "rid=" );
|
||||
if ( rid_ptr == NULL
|
||||
|| rid_ptr > &cookie->octet_str.bv_val[ cookie->octet_str.bv_len - STRLENOF( "rid=" ) ] )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
cookie->ctxcsn = NULL;
|
||||
cookie->sids = NULL;
|
||||
cookie->numcsns = 0;
|
||||
|
||||
if ( rid_ptr[ STRLENOF( "rid=" ) ] == '-' ) {
|
||||
return -1;
|
||||
}
|
||||
cookie->rid = strtoul( &rid_ptr[ STRLENOF( "rid=" ) ], &next, 10 );
|
||||
if ( next == &rid_ptr[ STRLENOF( "rid=" ) ] || ( next[ 0 ] != ',' && next[ 0 ] != '\0' ) ) {
|
||||
return -1;
|
||||
}
|
||||
end = cookie->octet_str.bv_val + cookie->octet_str.bv_len;
|
||||
|
||||
while (( csn_ptr = strstr( cookie->octet_str.bv_val, "csn=" )) != NULL ) {
|
||||
AttributeDescription *ad = slap_schema.si_ad_modifyTimestamp;
|
||||
slap_syntax_validate_func *validate;
|
||||
struct berval stamp;
|
||||
|
||||
/* This only happens when called from main */
|
||||
if ( ad == NULL )
|
||||
break;
|
||||
|
||||
if ( csn_ptr >= &cookie->octet_str.bv_val[ cookie->octet_str.bv_len - STRLENOF( "csn=" ) ] ) {
|
||||
return -1;
|
||||
for ( next=cookie->octet_str.bv_val; next < end; ) {
|
||||
if ( !strncmp( next, "rid=", STRLENOF("rid=") )) {
|
||||
rid_ptr = next;
|
||||
cookie->rid = strtoul( &rid_ptr[ STRLENOF( "rid=" ) ], &next, 10 );
|
||||
if ( next == rid_ptr || next > end || *next != ',' ) {
|
||||
return -1;
|
||||
}
|
||||
if ( *next == ',' ) {
|
||||
next++;
|
||||
}
|
||||
if ( !ad ) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ( !strncmp( next, "csn=", STRLENOF("csn=") )) {
|
||||
slap_syntax_validate_func *validate;
|
||||
struct berval stamp;
|
||||
|
||||
csn_str = csn_ptr + STRLENOF("csn=");
|
||||
cval = strchr( csn_str, ',' );
|
||||
if ( cval && cval < &cookie->octet_str.bv_val[ cookie->octet_str.bv_len ] )
|
||||
csn_str_len = cval - csn_str;
|
||||
else
|
||||
csn_str_len = 0;
|
||||
|
||||
/* FIXME use csnValidate when it gets implemented */
|
||||
csn_ptr = strchr( csn_str, '#' );
|
||||
if ( !csn_ptr || csn_str >= &cookie->octet_str.bv_val[ cookie->octet_str.bv_len ] ) break;
|
||||
|
||||
stamp.bv_val = csn_str;
|
||||
stamp.bv_len = csn_ptr - csn_str;
|
||||
validate = ad->ad_type->sat_syntax->ssyn_validate;
|
||||
if ( validate( ad->ad_type->sat_syntax, &stamp ) != LDAP_SUCCESS )
|
||||
break;
|
||||
valid = 1;
|
||||
break;
|
||||
csn_str = next + STRLENOF("csn=");
|
||||
while ( next < end ) {
|
||||
/* FIXME use csnValidate when it gets implemented */
|
||||
csn_ptr = strchr( csn_str, '#' );
|
||||
if ( !csn_ptr || csn_ptr > end )
|
||||
break;
|
||||
/* ad will be NULL when called from main. we just
|
||||
* want to parse the rid then. But we still iterate
|
||||
* through the string to find the end.
|
||||
*/
|
||||
if ( ad ) {
|
||||
stamp.bv_val = csn_str;
|
||||
stamp.bv_len = csn_ptr - csn_str;
|
||||
validate = ad->ad_type->sat_syntax->ssyn_validate;
|
||||
if ( validate( ad->ad_type->sat_syntax, &stamp )
|
||||
!= LDAP_SUCCESS )
|
||||
break;
|
||||
}
|
||||
cval = strchr( csn_ptr, ';' );
|
||||
if ( !cval )
|
||||
cval = strchr(csn_ptr, ',' );
|
||||
if ( cval )
|
||||
stamp.bv_len = cval - csn_str;
|
||||
else
|
||||
stamp.bv_len = end - csn_str;
|
||||
if ( ad ) {
|
||||
value_add_one( &cookie->ctxcsn, &stamp );
|
||||
cookie->numcsns++;
|
||||
}
|
||||
if ( cval ) {
|
||||
next = cval + 1;
|
||||
if ( *cval != ';' )
|
||||
break;
|
||||
} else {
|
||||
next = end;
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
next++;
|
||||
}
|
||||
if ( valid ) {
|
||||
ber_str2bv_x( csn_str, csn_str_len, 1, &cookie->ctxcsn, memctx );
|
||||
} else {
|
||||
BER_BVZERO( &cookie->ctxcsn );
|
||||
if ( cookie->numcsns ) {
|
||||
cookie->sids = slap_parse_csn_sids( cookie->ctxcsn, cookie->numcsns );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -189,7 +254,9 @@ slap_init_sync_cookie_ctxcsn(
|
|||
|
||||
ctxcsn.bv_val = octet_str.bv_val + 4;
|
||||
ctxcsn.bv_len = octet_str.bv_len - 4;
|
||||
ber_dupbv( &cookie->ctxcsn, &ctxcsn );
|
||||
cookie->ctxcsn = NULL;
|
||||
value_add_one( &cookie->ctxcsn, &ctxcsn );
|
||||
cookie->numcsns = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -201,14 +268,16 @@ slap_dup_sync_cookie(
|
|||
)
|
||||
{
|
||||
struct sync_cookie *new;
|
||||
int i;
|
||||
|
||||
if ( src == NULL )
|
||||
return NULL;
|
||||
|
||||
if ( dst ) {
|
||||
ch_free( dst->ctxcsn.bv_val );
|
||||
ber_bvarray_free( dst->ctxcsn );
|
||||
dst->ctxcsn = NULL;
|
||||
dst->sids = NULL;
|
||||
ch_free( dst->octet_str.bv_val );
|
||||
BER_BVZERO( &dst->ctxcsn );
|
||||
BER_BVZERO( &dst->octet_str );
|
||||
new = dst;
|
||||
} else {
|
||||
|
|
@ -217,9 +286,18 @@ slap_dup_sync_cookie(
|
|||
}
|
||||
|
||||
new->rid = src->rid;
|
||||
new->numcsns = src->numcsns;
|
||||
|
||||
if ( !BER_BVISNULL( &src->ctxcsn )) {
|
||||
ber_dupbv( &new->ctxcsn, &src->ctxcsn );
|
||||
if ( src->numcsns ) {
|
||||
if ( ber_bvarray_dup_x( &new->ctxcsn, src->ctxcsn, NULL )) {
|
||||
if ( !dst ) {
|
||||
ch_free( new );
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
new->sids = ch_malloc( src->numcsns * sizeof(int) );
|
||||
for (i=0; i<src->numcsns; i++)
|
||||
new->sids[i] = src->sids[i];
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &src->octet_str )) {
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ typedef struct slog_entry {
|
|||
struct slog_entry *se_next;
|
||||
struct berval se_uuid;
|
||||
struct berval se_csn;
|
||||
int se_sid;
|
||||
ber_tag_t se_tag;
|
||||
} slog_entry;
|
||||
|
||||
|
|
@ -118,7 +119,9 @@ typedef struct sessionlog {
|
|||
/* The main state for this overlay */
|
||||
typedef struct syncprov_info_t {
|
||||
syncops *si_ops;
|
||||
struct berval si_ctxcsn; /* ldapsync context */
|
||||
BerVarray si_ctxcsn; /* ldapsync context */
|
||||
int *si_sids;
|
||||
int si_numcsns;
|
||||
int si_chkops; /* checkpointing info */
|
||||
int si_chktime;
|
||||
int si_numops; /* number of ops since last checkpoint */
|
||||
|
|
@ -130,7 +133,6 @@ typedef struct syncprov_info_t {
|
|||
ldap_pvt_thread_mutex_t si_csn_mutex;
|
||||
ldap_pvt_thread_mutex_t si_ops_mutex;
|
||||
ldap_pvt_thread_mutex_t si_mods_mutex;
|
||||
char si_ctxcsnbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
|
||||
} syncprov_info_t;
|
||||
|
||||
typedef struct opcookie {
|
||||
|
|
@ -590,13 +592,10 @@ syncprov_findcsn( Operation *op, find_csn_t mode )
|
|||
sync_control *srs = NULL;
|
||||
struct slap_limits_set fc_limits;
|
||||
int i, rc = LDAP_SUCCESS, findcsn_retry = 1;
|
||||
int maxid = 0;
|
||||
|
||||
if ( mode != FIND_MAXCSN ) {
|
||||
srs = op->o_controls[slap_cids.sc_LDAPsync];
|
||||
|
||||
if ( srs->sr_state.ctxcsn.bv_len >= LDAP_LUTIL_CSNSTR_BUFSIZE ) {
|
||||
return LDAP_OTHER;
|
||||
}
|
||||
}
|
||||
|
||||
fop = *op;
|
||||
|
|
@ -606,6 +605,7 @@ syncprov_findcsn( Operation *op, find_csn_t mode )
|
|||
|
||||
cf.f_ava = &eq;
|
||||
cf.f_av_desc = slap_schema.si_ad_entryCSN;
|
||||
BER_BVZERO( &cf.f_av_value );
|
||||
cf.f_next = NULL;
|
||||
|
||||
fop.o_callback = &cb;
|
||||
|
|
@ -618,7 +618,14 @@ again:
|
|||
switch( mode ) {
|
||||
case FIND_MAXCSN:
|
||||
cf.f_choice = LDAP_FILTER_GE;
|
||||
cf.f_av_value = si->si_ctxcsn;
|
||||
cf.f_av_value = si->si_ctxcsn[0];
|
||||
/* If there are multiple CSNs, use the largest */
|
||||
for ( i=1; i<si->si_numcsns; i++) {
|
||||
if ( ber_bvcmp( &cf.f_av_value, &si->si_ctxcsn[i] ) < 0 ) {
|
||||
cf.f_av_value = si->si_ctxcsn[i];
|
||||
maxid = i;
|
||||
}
|
||||
}
|
||||
fop.ors_filterstr.bv_len = sprintf( buf, "(entryCSN>=%s)",
|
||||
cf.f_av_value.bv_val );
|
||||
fop.ors_attrsonly = 0;
|
||||
|
|
@ -626,12 +633,21 @@ again:
|
|||
fop.ors_slimit = SLAP_NO_LIMIT;
|
||||
cb.sc_private = &maxcsn;
|
||||
cb.sc_response = findmax_cb;
|
||||
strcpy( cbuf, si->si_ctxcsn.bv_val );
|
||||
strcpy( cbuf, cf.f_av_value.bv_val );
|
||||
maxcsn.bv_val = cbuf;
|
||||
maxcsn.bv_len = si->si_ctxcsn.bv_len;
|
||||
maxcsn.bv_len = cf.f_av_value.bv_len;
|
||||
break;
|
||||
case FIND_CSN:
|
||||
cf.f_av_value = srs->sr_state.ctxcsn;
|
||||
if ( BER_BVISEMPTY( &cf.f_av_value )) {
|
||||
cf.f_av_value = srs->sr_state.ctxcsn[0];
|
||||
/* If there are multiple CSNs, use the smallest */
|
||||
for ( i=1; i<srs->sr_state.numcsns; i++ ) {
|
||||
if ( ber_bvcmp( &cf.f_av_value, &srs->sr_state.ctxcsn[i] )
|
||||
> 0 ) {
|
||||
cf.f_av_value = srs->sr_state.ctxcsn[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Look for exact match the first time */
|
||||
if ( findcsn_retry ) {
|
||||
cf.f_choice = LDAP_FILTER_EQUALITY;
|
||||
|
|
@ -681,8 +697,10 @@ again:
|
|||
|
||||
switch( mode ) {
|
||||
case FIND_MAXCSN:
|
||||
strcpy( si->si_ctxcsnbuf, maxcsn.bv_val );
|
||||
si->si_ctxcsn.bv_len = maxcsn.bv_len;
|
||||
if ( ber_bvcmp( &si->si_ctxcsn[maxid], &maxcsn )) {
|
||||
ber_bvreplace( &si->si_ctxcsn[maxid], &maxcsn );
|
||||
si->si_numops++; /* ensure a checkpoint */
|
||||
}
|
||||
break;
|
||||
case FIND_CSN:
|
||||
/* If matching CSN was not found, invalidate the context. */
|
||||
|
|
@ -741,7 +759,7 @@ syncprov_sendresp( Operation *op, opcookie *opc, syncops *so,
|
|||
|
||||
SlapReply rs = { REP_SEARCH };
|
||||
LDAPControl *ctrls[2];
|
||||
struct berval cookie;
|
||||
struct berval cookie, csns[2];
|
||||
Entry e_uuid = {0};
|
||||
Attribute a_uuid = {0};
|
||||
|
||||
|
|
@ -749,7 +767,9 @@ syncprov_sendresp( Operation *op, opcookie *opc, syncops *so,
|
|||
return SLAPD_ABANDON;
|
||||
|
||||
ctrls[1] = NULL;
|
||||
slap_compose_sync_cookie( op, &cookie, &opc->sctxcsn, so->s_rid );
|
||||
csns[0] = opc->sctxcsn;
|
||||
BER_BVZERO( &csns[1] );
|
||||
slap_compose_sync_cookie( op, &cookie, csns, so->s_rid );
|
||||
|
||||
e_uuid.e_attrs = &a_uuid;
|
||||
a_uuid.a_desc = slap_schema.si_ad_entryUUID;
|
||||
|
|
@ -1256,23 +1276,15 @@ syncprov_op_cleanup( Operation *op, SlapReply *rs )
|
|||
}
|
||||
|
||||
static void
|
||||
syncprov_checkpoint( Operation *op, SlapReply *rs, slap_overinst *on,
|
||||
struct berval *csn )
|
||||
syncprov_checkpoint( Operation *op, SlapReply *rs, slap_overinst *on )
|
||||
{
|
||||
syncprov_info_t *si = (syncprov_info_t *)on->on_bi.bi_private;
|
||||
Modifications mod;
|
||||
Operation opm;
|
||||
SlapReply rsm = { 0 };
|
||||
struct berval bv[2];
|
||||
slap_callback cb = {0};
|
||||
|
||||
/* If ctxcsn is empty, delete it */
|
||||
if ( BER_BVISEMPTY( csn )) {
|
||||
mod.sml_values = NULL;
|
||||
} else {
|
||||
mod.sml_values = bv;
|
||||
bv[1].bv_val = NULL;
|
||||
bv[0] = *csn;
|
||||
}
|
||||
mod.sml_values = si->si_ctxcsn;
|
||||
mod.sml_nvalues = NULL;
|
||||
mod.sml_desc = slap_schema.si_ad_contextCSN;
|
||||
mod.sml_op = LDAP_MOD_REPLACE;
|
||||
|
|
@ -1284,13 +1296,12 @@ syncprov_checkpoint( Operation *op, SlapReply *rs, slap_overinst *on,
|
|||
opm.o_tag = LDAP_REQ_MODIFY;
|
||||
opm.o_callback = &cb;
|
||||
opm.orm_modlist = &mod;
|
||||
opm.orm_no_opattrs = 1;
|
||||
opm.o_req_dn = op->o_bd->be_suffix[0];
|
||||
opm.o_req_ndn = op->o_bd->be_nsuffix[0];
|
||||
opm.o_bd->bd_info = on->on_info->oi_orig;
|
||||
opm.o_managedsait = SLAP_CONTROL_NONCRITICAL;
|
||||
SLAP_DBFLAGS( opm.o_bd ) |= SLAP_DBFLAG_NOLASTMOD;
|
||||
opm.o_bd->be_modify( &opm, &rsm );
|
||||
SLAP_DBFLAGS( opm.o_bd ) ^= SLAP_DBFLAG_NOLASTMOD;
|
||||
if ( mod.sml_next != NULL ) {
|
||||
slap_mods_free( mod.sml_next, 1 );
|
||||
}
|
||||
|
|
@ -1321,6 +1332,7 @@ syncprov_add_slog( Operation *op )
|
|||
AC_MEMCPY( se->se_csn.bv_val, op->o_csn.bv_val, op->o_csn.bv_len );
|
||||
se->se_csn.bv_val[op->o_csn.bv_len] = '\0';
|
||||
se->se_csn.bv_len = op->o_csn.bv_len;
|
||||
se->se_sid = slap_parse_csn_sid( &se->se_csn );
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &sl->sl_mutex );
|
||||
if ( sl->sl_head ) {
|
||||
|
|
@ -1355,14 +1367,14 @@ playlog_cb( Operation *op, SlapReply *rs )
|
|||
/* enter with sl->sl_mutex locked, release before returning */
|
||||
static void
|
||||
syncprov_playlog( Operation *op, SlapReply *rs, sessionlog *sl,
|
||||
sync_control *srs, struct berval *ctxcsn )
|
||||
sync_control *srs, BerVarray ctxcsn, int numcsns, int *sids )
|
||||
{
|
||||
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
|
||||
slog_entry *se;
|
||||
int i, j, ndel, num, nmods, mmods;
|
||||
char cbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
|
||||
BerVarray uuids;
|
||||
struct berval delcsn;
|
||||
struct berval delcsn[2];
|
||||
|
||||
if ( !sl->sl_num ) {
|
||||
ldap_pvt_thread_mutex_unlock( &sl->sl_mutex );
|
||||
|
|
@ -1377,35 +1389,47 @@ syncprov_playlog( Operation *op, SlapReply *rs, sessionlog *sl,
|
|||
num * UUID_LEN, op->o_tmpmemctx );
|
||||
uuids[0].bv_val = (char *)(uuids + num + 1);
|
||||
|
||||
delcsn.bv_len = 0;
|
||||
delcsn.bv_val = cbuf;
|
||||
delcsn[0].bv_len = 0;
|
||||
delcsn[0].bv_val = cbuf;
|
||||
BER_BVZERO(&delcsn[1]);
|
||||
|
||||
/* Make a copy of the relevant UUIDs. Put the Deletes up front
|
||||
* and everything else at the end. Do this first so we can
|
||||
* unlock the list mutex.
|
||||
*/
|
||||
Debug( LDAP_DEBUG_SYNC, "srs csn %s\n", srs-> sr_state.ctxcsn.bv_val, 0, 0 );
|
||||
Debug( LDAP_DEBUG_SYNC, "srs csn %s\n",
|
||||
srs->sr_state.ctxcsn[0].bv_val, 0, 0 );
|
||||
for ( se=sl->sl_head; se; se=se->se_next ) {
|
||||
Debug( LDAP_DEBUG_SYNC, "log csn %s\n", se-> se_csn.bv_val,
|
||||
0, 0 );
|
||||
ndel = ber_bvcmp( &se->se_csn, &srs->sr_state.ctxcsn );
|
||||
if ( ndel <= 0 ) {
|
||||
Debug( LDAP_DEBUG_SYNC, "cmp %d, too old\n", ndel,
|
||||
0, 0 );
|
||||
continue;
|
||||
}
|
||||
ndel = ber_bvcmp( &se->se_csn, ctxcsn );
|
||||
if ( ndel > 0 ) {
|
||||
Debug( LDAP_DEBUG_SYNC, "cmp %d, too new\n", ndel,
|
||||
0, 0 );
|
||||
break;
|
||||
}
|
||||
int k;
|
||||
Debug( LDAP_DEBUG_SYNC, "log csn %s\n", se->se_csn.bv_val, 0, 0 );
|
||||
ndel = 1;
|
||||
for ( k=0; k<srs->sr_state.numcsns; k++ ) {
|
||||
if ( se->se_sid == srs->sr_state.sids[k] ) {
|
||||
ndel = ber_bvcmp( &se->se_csn, &srs->sr_state.ctxcsn[k] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( ndel <= 0 ) {
|
||||
Debug( LDAP_DEBUG_SYNC, "cmp %d, too old\n", ndel, 0, 0 );
|
||||
continue;
|
||||
}
|
||||
ndel = 0;
|
||||
for ( k=0; k<numcsns; k++ ) {
|
||||
if ( se->se_sid == sids[k] ) {
|
||||
ndel = ber_bvcmp( &se->se_csn, &ctxcsn[k] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( ndel > 0 ) {
|
||||
Debug( LDAP_DEBUG_SYNC, "cmp %d, too new\n", ndel, 0, 0 );
|
||||
break;
|
||||
}
|
||||
if ( se->se_tag == LDAP_REQ_DELETE ) {
|
||||
j = i;
|
||||
i++;
|
||||
AC_MEMCPY( cbuf, se->se_csn.bv_val, se->se_csn.bv_len );
|
||||
delcsn.bv_len = se->se_csn.bv_len;
|
||||
delcsn.bv_val[delcsn.bv_len] = '\0';
|
||||
delcsn[0].bv_len = se->se_csn.bv_len;
|
||||
delcsn[0].bv_val[delcsn[0].bv_len] = '\0';
|
||||
} else {
|
||||
nmods++;
|
||||
j = num - nmods;
|
||||
|
|
@ -1499,7 +1523,7 @@ syncprov_playlog( Operation *op, SlapReply *rs, sessionlog *sl,
|
|||
if ( ndel ) {
|
||||
struct berval cookie;
|
||||
|
||||
slap_compose_sync_cookie( op, &cookie, &delcsn, srs->sr_state.rid );
|
||||
slap_compose_sync_cookie( op, &cookie, delcsn, srs->sr_state.rid );
|
||||
uuids[ndel].bv_val = NULL;
|
||||
syncprov_sendinfo( op, rs, LDAP_TAG_SYNC_ID_SET, &cookie, 0, uuids, 1 );
|
||||
op->o_tmpfree( cookie.bv_val, op->o_tmpmemctx );
|
||||
|
|
@ -1526,10 +1550,24 @@ syncprov_op_response( Operation *op, SlapReply *rs )
|
|||
ldap_pvt_thread_mutex_lock( &si->si_csn_mutex );
|
||||
slap_get_commit_csn( op, &maxcsn );
|
||||
if ( !BER_BVISNULL( &maxcsn ) ) {
|
||||
int i, sid;
|
||||
strcpy( cbuf, maxcsn.bv_val );
|
||||
if ( ber_bvcmp( &maxcsn, &si->si_ctxcsn ) > 0 ) {
|
||||
strcpy( si->si_ctxcsnbuf, cbuf );
|
||||
si->si_ctxcsn.bv_len = maxcsn.bv_len;
|
||||
sid = slap_parse_csn_sid( &maxcsn );
|
||||
for ( i=0; i<si->si_numcsns; i++ ) {
|
||||
if ( sid == si->si_sids[i] ) {
|
||||
if ( ber_bvcmp( &maxcsn, &si->si_ctxcsn[i] ) > 0 ) {
|
||||
ber_bvreplace( &si->si_ctxcsn[i], &maxcsn );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* It's a new SID for us */
|
||||
if ( i == si->si_numcsns ) {
|
||||
value_add_one( &si->si_ctxcsn, &maxcsn );
|
||||
si->si_numcsns++;
|
||||
si->si_sids = ch_realloc( si->si_sids, si->si_numcsns *
|
||||
sizeof(int));
|
||||
si->si_sids[i] = sid;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1558,7 +1596,7 @@ syncprov_op_response( Operation *op, SlapReply *rs )
|
|||
opc->sctxcsn.bv_val = cbuf;
|
||||
|
||||
if ( do_check ) {
|
||||
syncprov_checkpoint( op, rs, on, &opc->sctxcsn );
|
||||
syncprov_checkpoint( op, rs, on );
|
||||
}
|
||||
|
||||
/* Handle any persistent searches */
|
||||
|
|
@ -1608,20 +1646,18 @@ syncprov_op_compare( Operation *op, SlapReply *rs )
|
|||
{
|
||||
Entry e = {0};
|
||||
Attribute a = {0};
|
||||
struct berval bv[2];
|
||||
|
||||
e.e_name = op->o_bd->be_suffix[0];
|
||||
e.e_nname = op->o_bd->be_nsuffix[0];
|
||||
|
||||
BER_BVZERO( &bv[1] );
|
||||
bv[0] = si->si_ctxcsn;
|
||||
e.e_attrs = &a;
|
||||
|
||||
a.a_desc = slap_schema.si_ad_contextCSN;
|
||||
a.a_vals = bv;
|
||||
a.a_nvals = a.a_vals;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &si->si_csn_mutex );
|
||||
|
||||
a.a_vals = si->si_ctxcsn;
|
||||
a.a_nvals = a.a_vals;
|
||||
|
||||
rs->sr_err = access_allowed( op, &e, op->oq_compare.rs_ava->aa_desc,
|
||||
&op->oq_compare.rs_ava->aa_value, ACL_COMPARE, NULL );
|
||||
if ( ! rs->sr_err ) {
|
||||
|
|
@ -1748,9 +1784,10 @@ syncprov_op_extended( Operation *op, SlapReply *rs )
|
|||
typedef struct searchstate {
|
||||
slap_overinst *ss_on;
|
||||
syncops *ss_so;
|
||||
BerVarray ss_ctxcsn;
|
||||
int *ss_sids;
|
||||
int ss_numcsns;
|
||||
int ss_present;
|
||||
struct berval ss_ctxcsn;
|
||||
char ss_csnbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
|
||||
} searchstate;
|
||||
|
||||
static int
|
||||
|
|
@ -1879,23 +1916,36 @@ syncprov_search_response( Operation *op, SlapReply *rs )
|
|||
a = attr_find( rs->sr_operational_attrs, slap_schema.si_ad_entryCSN );
|
||||
}
|
||||
if ( a ) {
|
||||
int i, sid;
|
||||
sid = slap_parse_csn_sid( &a->a_nvals[0] );
|
||||
|
||||
/* Make sure entry is less than the snapshot'd contextCSN */
|
||||
if ( ber_bvcmp( &a->a_nvals[0], &ss->ss_ctxcsn ) > 0 ) {
|
||||
Debug( LDAP_DEBUG_SYNC, "Entry %s CSN %s greater than snapshot %s\n",
|
||||
rs->sr_entry->e_name.bv_val,
|
||||
a->a_nvals[0].bv_val,
|
||||
ss->ss_ctxcsn.bv_val );
|
||||
return LDAP_SUCCESS;
|
||||
for ( i=0; i<ss->ss_numcsns; i++ ) {
|
||||
if ( sid == ss->ss_sids[i] && ber_bvcmp( &a->a_nvals[0],
|
||||
&ss->ss_ctxcsn[i] ) > 0 ) {
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"Entry %s CSN %s greater than snapshot %s\n",
|
||||
rs->sr_entry->e_name.bv_val,
|
||||
a->a_nvals[0].bv_val,
|
||||
ss->ss_ctxcsn[i].bv_val );
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't send the ctx entry twice */
|
||||
if ( !BER_BVISNULL( &srs->sr_state.ctxcsn ) &&
|
||||
bvmatch( &a->a_nvals[0], &srs->sr_state.ctxcsn ) ) {
|
||||
Debug( LDAP_DEBUG_SYNC, "Entry %s CSN %s matches ctx %s\n",
|
||||
rs->sr_entry->e_name.bv_val,
|
||||
a->a_nvals[0].bv_val,
|
||||
srs->sr_state.ctxcsn.bv_val );
|
||||
return LDAP_SUCCESS;
|
||||
/* Don't send old entries twice */
|
||||
if ( srs->sr_state.ctxcsn ) {
|
||||
for ( i=0; i<srs->sr_state.numcsns; i++ ) {
|
||||
if ( sid == srs->sr_state.sids[i] &&
|
||||
ber_bvcmp( &a->a_nvals[0],
|
||||
&srs->sr_state.ctxcsn[i] )<= 0 ) {
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"Entry %s CSN %s older or equal to ctx %s\n",
|
||||
rs->sr_entry->e_name.bv_val,
|
||||
a->a_nvals[0].bv_val,
|
||||
srs->sr_state.ctxcsn[i].bv_val );
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
rs->sr_ctrls = op->o_tmpalloc( sizeof(LDAPControl *)*2,
|
||||
|
|
@ -1906,7 +1956,7 @@ syncprov_search_response( Operation *op, SlapReply *rs )
|
|||
} else if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS ) {
|
||||
struct berval cookie;
|
||||
|
||||
slap_compose_sync_cookie( op, &cookie, &ss->ss_ctxcsn,
|
||||
slap_compose_sync_cookie( op, &cookie, ss->ss_ctxcsn,
|
||||
srs->sr_state.rid );
|
||||
|
||||
/* Is this a regular refresh? */
|
||||
|
|
@ -1955,8 +2005,9 @@ syncprov_op_search( Operation *op, SlapReply *rs )
|
|||
syncops *sop = NULL;
|
||||
searchstate *ss;
|
||||
sync_control *srs;
|
||||
struct berval ctxcsn;
|
||||
char csnbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
|
||||
BerVarray ctxcsn;
|
||||
int i, *sids, numcsns;
|
||||
struct berval mincsn;
|
||||
|
||||
if ( !(op->o_sync_mode & SLAP_SYNC_REFRESH) ) return SLAP_CB_CONTINUE;
|
||||
|
||||
|
|
@ -2010,34 +2061,77 @@ syncprov_op_search( Operation *op, SlapReply *rs )
|
|||
|
||||
/* snapshot the ctxcsn */
|
||||
ldap_pvt_thread_mutex_lock( &si->si_csn_mutex );
|
||||
strcpy( csnbuf, si->si_ctxcsnbuf );
|
||||
ctxcsn.bv_len = si->si_ctxcsn.bv_len;
|
||||
ber_bvarray_dup_x( &ctxcsn, si->si_ctxcsn, op->o_tmpmemctx );
|
||||
numcsns = si->si_numcsns;
|
||||
sids = op->o_tmpalloc( numcsns * sizeof(int), op->o_tmpmemctx );
|
||||
for ( i=0; i<numcsns; i++ )
|
||||
sids[i] = si->si_sids[i];
|
||||
ldap_pvt_thread_mutex_unlock( &si->si_csn_mutex );
|
||||
ctxcsn.bv_val = csnbuf;
|
||||
|
||||
/* If we have a cookie, handle the PRESENT lookups */
|
||||
if ( !BER_BVISNULL( &srs->sr_state.ctxcsn )) {
|
||||
if ( srs->sr_state.ctxcsn ) {
|
||||
sessionlog *sl;
|
||||
int i, j;
|
||||
|
||||
/* The cookie was validated when it was parsed, just use it */
|
||||
|
||||
/* If just Refreshing and nothing has changed, shortcut it */
|
||||
if ( bvmatch( &srs->sr_state.ctxcsn, &ctxcsn )) {
|
||||
nochange = 1;
|
||||
if ( !(op->o_sync_mode & SLAP_SYNC_PERSIST) ) {
|
||||
LDAPControl *ctrls[2];
|
||||
|
||||
ctrls[0] = NULL;
|
||||
ctrls[1] = NULL;
|
||||
syncprov_done_ctrl( op, rs, ctrls, 0, 0,
|
||||
NULL, LDAP_SYNC_REFRESH_DELETES );
|
||||
rs->sr_ctrls = ctrls;
|
||||
rs->sr_err = LDAP_SUCCESS;
|
||||
send_ldap_result( op, rs );
|
||||
rs->sr_ctrls = NULL;
|
||||
return rs->sr_err;
|
||||
/* If there are SIDs we don't recognize in the cookie, drop them */
|
||||
for (i=0; i<srs->sr_state.numcsns; ) {
|
||||
for (j=0; j<numcsns; j++) {
|
||||
if ( srs->sr_state.sids[i] == sids[j] ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* not found */
|
||||
if ( j == numcsns ) {
|
||||
struct berval tmp = srs->sr_state.ctxcsn[i];
|
||||
j = srs->sr_state.numcsns - 1;
|
||||
srs->sr_state.ctxcsn[i] = srs->sr_state.ctxcsn[j];
|
||||
tmp.bv_len = 0;
|
||||
srs->sr_state.ctxcsn[j] = tmp;
|
||||
srs->sr_state.numcsns = j;
|
||||
srs->sr_state.sids[i] = srs->sr_state.sids[j];
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Find the smallest CSN */
|
||||
mincsn = srs->sr_state.ctxcsn[0];
|
||||
for ( i=1; i<srs->sr_state.numcsns; i++ ) {
|
||||
if ( ber_bvcmp( &mincsn, &srs->sr_state.ctxcsn[i] ) > 0 )
|
||||
mincsn = srs->sr_state.ctxcsn[i];
|
||||
}
|
||||
|
||||
/* If nothing has changed, shortcut it */
|
||||
if ( srs->sr_state.numcsns == numcsns ) {
|
||||
int i, j, changed = 0;
|
||||
for ( i=0; i<srs->sr_state.numcsns; i++ ) {
|
||||
for ( j=0; j<numcsns; j++ ) {
|
||||
if ( srs->sr_state.sids[i] != sids[j] )
|
||||
continue;
|
||||
if ( !bvmatch( &srs->sr_state.ctxcsn[i], &ctxcsn[j] ))
|
||||
changed = 1;
|
||||
break;
|
||||
}
|
||||
if ( changed )
|
||||
break;
|
||||
}
|
||||
if ( !changed ) {
|
||||
nochange = 1;
|
||||
if ( !(op->o_sync_mode & SLAP_SYNC_PERSIST) ) {
|
||||
LDAPControl *ctrls[2];
|
||||
|
||||
ctrls[0] = NULL;
|
||||
ctrls[1] = NULL;
|
||||
syncprov_done_ctrl( op, rs, ctrls, 0, 0,
|
||||
NULL, LDAP_SYNC_REFRESH_DELETES );
|
||||
rs->sr_ctrls = ctrls;
|
||||
rs->sr_err = LDAP_SUCCESS;
|
||||
send_ldap_result( op, rs );
|
||||
rs->sr_ctrls = NULL;
|
||||
return rs->sr_err;
|
||||
}
|
||||
goto shortcut;
|
||||
}
|
||||
goto shortcut;
|
||||
}
|
||||
/* Do we have a sessionlog for this search? */
|
||||
sl=si->si_logs;
|
||||
|
|
@ -2046,10 +2140,10 @@ syncprov_op_search( Operation *op, SlapReply *rs )
|
|||
/* Are there any log entries, and is the consumer state
|
||||
* present in the session log?
|
||||
*/
|
||||
if ( sl->sl_num > 0 && ber_bvcmp( &srs->sr_state.ctxcsn, &sl->sl_mincsn ) >= 0 ) {
|
||||
if ( sl->sl_num > 0 && ber_bvcmp( &mincsn, &sl->sl_mincsn ) >= 0 ) {
|
||||
do_present = 0;
|
||||
/* mutex is unlocked in playlog */
|
||||
syncprov_playlog( op, rs, sl, srs, &ctxcsn );
|
||||
syncprov_playlog( op, rs, sl, srs, ctxcsn, numcsns, sids );
|
||||
} else {
|
||||
ldap_pvt_thread_mutex_unlock( &sl->sl_mutex );
|
||||
}
|
||||
|
|
@ -2096,7 +2190,7 @@ shortcut:
|
|||
#ifdef LDAP_COMP_MATCH
|
||||
fava->f_ava->aa_cf = NULL;
|
||||
#endif
|
||||
ber_dupbv_x( &fava->f_ava->aa_value, &srs->sr_state.ctxcsn, op->o_tmpmemctx );
|
||||
ber_dupbv_x( &fava->f_ava->aa_value, &mincsn, op->o_tmpmemctx );
|
||||
fava->f_next = op->ors_filter;
|
||||
op->ors_filter = fand;
|
||||
filter2bv_x( op, op->ors_filter, &op->ors_filterstr );
|
||||
|
|
@ -2110,19 +2204,15 @@ shortcut:
|
|||
ss->ss_on = on;
|
||||
ss->ss_so = sop;
|
||||
ss->ss_present = do_present;
|
||||
ss->ss_ctxcsn.bv_len = ctxcsn.bv_len;
|
||||
ss->ss_ctxcsn.bv_val = ss->ss_csnbuf;
|
||||
strcpy( ss->ss_ctxcsn.bv_val, ctxcsn.bv_val );
|
||||
ss->ss_ctxcsn = ctxcsn;
|
||||
ss->ss_numcsns = numcsns;
|
||||
ss->ss_sids = sids;
|
||||
cb->sc_response = syncprov_search_response;
|
||||
cb->sc_cleanup = syncprov_search_cleanup;
|
||||
cb->sc_private = ss;
|
||||
cb->sc_next = op->o_callback;
|
||||
op->o_callback = cb;
|
||||
|
||||
#if 0 /* I don't think we need to shortcircuit back-bdb any more */
|
||||
op->o_sync_mode &= SLAP_CONTROL_MASK;
|
||||
#endif
|
||||
|
||||
/* If this is a persistent search and no changes were reported during
|
||||
* the refresh phase, just invoke the response callback to transition
|
||||
* us into persist phase
|
||||
|
|
@ -2156,21 +2246,28 @@ syncprov_operational(
|
|||
break;
|
||||
}
|
||||
|
||||
if ( !a ) {
|
||||
for ( ap = &rs->sr_operational_attrs; *ap; ap=&(*ap)->a_next );
|
||||
|
||||
a = attr_alloc( slap_schema.si_ad_contextCSN );
|
||||
a->a_vals = ch_malloc( 2 * sizeof(struct berval));
|
||||
a->a_vals[1].bv_val = NULL;
|
||||
a->a_nvals = a->a_vals;
|
||||
*ap = a;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &si->si_csn_mutex );
|
||||
if ( !ap ) {
|
||||
strcpy( a->a_vals[0].bv_val, si->si_ctxcsnbuf );
|
||||
} else {
|
||||
ber_dupbv( &a->a_vals[0], &si->si_ctxcsn );
|
||||
if ( si->si_ctxcsn ) {
|
||||
if ( !a ) {
|
||||
for ( ap = &rs->sr_operational_attrs; *ap;
|
||||
ap=&(*ap)->a_next );
|
||||
|
||||
a = attr_alloc( slap_schema.si_ad_contextCSN );
|
||||
*ap = a;
|
||||
}
|
||||
|
||||
if ( !ap ) {
|
||||
if ( !rs->sr_flags & REP_ENTRY_MODIFIABLE ) {
|
||||
rs->sr_entry = entry_dup( rs->sr_entry );
|
||||
rs->sr_flags |=
|
||||
REP_ENTRY_MODIFIABLE|REP_ENTRY_MUSTBEFREED;
|
||||
a = attr_find( rs->sr_entry->e_attrs,
|
||||
slap_schema.si_ad_contextCSN );
|
||||
}
|
||||
free( a->a_vals );
|
||||
}
|
||||
ber_bvarray_dup_x( &a->a_vals, si->si_ctxcsn, NULL );
|
||||
a->a_nvals = a->a_vals;
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &si->si_csn_mutex );
|
||||
}
|
||||
|
|
@ -2379,7 +2476,6 @@ syncprov_db_open(
|
|||
|
||||
Connection conn = { 0 };
|
||||
OperationBuffer opbuf = { 0 };
|
||||
char ctxcsnbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
|
||||
Operation *op = (Operation *) &opbuf;
|
||||
Entry *e;
|
||||
Attribute *a;
|
||||
|
|
@ -2407,8 +2503,6 @@ syncprov_db_open(
|
|||
op->o_dn = be->be_rootdn;
|
||||
op->o_ndn = be->be_rootndn;
|
||||
|
||||
ctxcsnbuf[0] = '\0';
|
||||
|
||||
op->o_bd->bd_info = on->on_info->oi_orig;
|
||||
rc = be_entry_get_rw( op, be->be_nsuffix, NULL,
|
||||
slap_schema.si_ad_contextCSN, 0, &e );
|
||||
|
|
@ -2418,16 +2512,14 @@ syncprov_db_open(
|
|||
|
||||
a = attr_find( e->e_attrs, slap_schema.si_ad_contextCSN );
|
||||
if ( a ) {
|
||||
si->si_ctxcsn.bv_len = a->a_nvals[0].bv_len;
|
||||
if ( si->si_ctxcsn.bv_len >= sizeof(si->si_ctxcsnbuf ))
|
||||
si->si_ctxcsn.bv_len = sizeof(si->si_ctxcsnbuf)-1;
|
||||
strncpy( si->si_ctxcsnbuf, a->a_nvals[0].bv_val,
|
||||
si->si_ctxcsn.bv_len );
|
||||
si->si_ctxcsnbuf[si->si_ctxcsn.bv_len] = '\0';
|
||||
strcpy( ctxcsnbuf, si->si_ctxcsnbuf );
|
||||
int i;
|
||||
ber_bvarray_dup_x( &si->si_ctxcsn, a->a_vals, NULL );
|
||||
for ( i=0; !BER_BVISEMPTY( &a->a_vals[i] ); i++ );
|
||||
si->si_numcsns = i;
|
||||
si->si_sids = slap_parse_csn_sids( si->si_ctxcsn, i );
|
||||
}
|
||||
be_entry_release_rw( op, e, 0 );
|
||||
if ( !BER_BVISEMPTY( &si->si_ctxcsn ) ) {
|
||||
if ( si->si_ctxcsn ) {
|
||||
op->o_bd->bd_info = (BackendInfo *)on;
|
||||
op->o_req_dn = be->be_suffix[0];
|
||||
op->o_req_ndn = be->be_nsuffix[0];
|
||||
|
|
@ -2437,22 +2529,27 @@ syncprov_db_open(
|
|||
}
|
||||
}
|
||||
|
||||
if ( BER_BVISEMPTY( &si->si_ctxcsn ) ) {
|
||||
if ( SLAP_SYNC_SHADOW( op->o_bd )) {
|
||||
/* If we're also a consumer, and we didn't get a contextCSN,
|
||||
/* Didn't find a contextCSN, should we generate one? */
|
||||
if ( !si->si_ctxcsn ) {
|
||||
char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ];
|
||||
struct berval csn;
|
||||
|
||||
if ( SLAP_SYNC_SHADOW( op->o_bd ) && SLAP_SINGLE_SHADOW( op->o_bd )) {
|
||||
/* If we're also a consumer, and we're not multimaster,
|
||||
* then don't generate anything, wait for our provider to send it
|
||||
* to us.
|
||||
*/
|
||||
goto out;
|
||||
}
|
||||
si->si_ctxcsn.bv_len = sizeof( si->si_ctxcsnbuf );
|
||||
slap_get_csn( op, &si->si_ctxcsn, 0 );
|
||||
}
|
||||
csn.bv_val = csnbuf;
|
||||
csn.bv_len = sizeof( csnbuf );
|
||||
slap_get_csn( op, &csn, 0 );
|
||||
value_add_one( &si->si_ctxcsn, &csn );
|
||||
si->si_numcsns = 1;
|
||||
si->si_sids = ch_malloc( sizeof(int) );
|
||||
si->si_sids[0] = slap_serverID;
|
||||
|
||||
/* If our ctxcsn is different from what was read from the root
|
||||
* entry, make sure we do a checkpoint on close
|
||||
*/
|
||||
if ( strcmp( si->si_ctxcsnbuf, ctxcsnbuf )) {
|
||||
/* make sure we do a checkpoint on close */
|
||||
si->si_numops++;
|
||||
}
|
||||
|
||||
|
|
@ -2486,7 +2583,7 @@ syncprov_db_close(
|
|||
op->o_bd = be;
|
||||
op->o_dn = be->be_rootdn;
|
||||
op->o_ndn = be->be_rootndn;
|
||||
syncprov_checkpoint( op, &rs, on, &si->si_ctxcsn );
|
||||
syncprov_checkpoint( op, &rs, on );
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -2512,7 +2609,6 @@ syncprov_db_init(
|
|||
ldap_pvt_thread_mutex_init( &si->si_csn_mutex );
|
||||
ldap_pvt_thread_mutex_init( &si->si_ops_mutex );
|
||||
ldap_pvt_thread_mutex_init( &si->si_mods_mutex );
|
||||
si->si_ctxcsn.bv_val = si->si_ctxcsnbuf;
|
||||
|
||||
csn_anlist[0].an_desc = slap_schema.si_ad_entryCSN;
|
||||
csn_anlist[0].an_name = slap_schema.si_ad_entryCSN->ad_cname;
|
||||
|
|
|
|||
|
|
@ -1016,9 +1016,13 @@ LDAP_SLAPD_V (char *) slap_known_controls[];
|
|||
* ldapsync.c
|
||||
*/
|
||||
LDAP_SLAPD_F (void) slap_compose_sync_cookie LDAP_P((
|
||||
Operation *, struct berval *, struct berval *, int ));
|
||||
Operation *, struct berval *, BerVarray, int ));
|
||||
LDAP_SLAPD_F (void) slap_sync_cookie_free LDAP_P((
|
||||
struct sync_cookie *, int free_cookie ));
|
||||
LDAP_SLAPD_F (int) slap_parse_csn_sid LDAP_P((
|
||||
struct berval * ));
|
||||
LDAP_SLAPD_F (int *) slap_parse_csn_sids LDAP_P((
|
||||
BerVarray, int ));
|
||||
LDAP_SLAPD_F (int) slap_parse_sync_cookie LDAP_P((
|
||||
struct sync_cookie *, void *memctx ));
|
||||
LDAP_SLAPD_F (int) slap_init_sync_cookie_ctxcsn LDAP_P((
|
||||
|
|
|
|||
|
|
@ -603,7 +603,7 @@ static struct slap_schema_ad_map {
|
|||
"EQUALITY CSNMatch "
|
||||
"ORDERING CSNOrderingMatch "
|
||||
"SYNTAX 1.3.6.1.4.1.4203.666.11.2.1{64} "
|
||||
"SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation )",
|
||||
"NO-USER-MODIFICATION USAGE dSAOperation )",
|
||||
NULL, SLAP_AT_HIDE,
|
||||
NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
|
|
|
|||
|
|
@ -1650,14 +1650,17 @@ typedef BackendDB Backend;
|
|||
struct syncinfo_s;
|
||||
|
||||
#define SLAP_SYNC_RID_SIZE 3
|
||||
#define SLAP_SYNC_SID_MAX 4095 /* based on liblutil/csn.c field width */
|
||||
#define SLAP_SYNCUUID_SET_SIZE 256
|
||||
|
||||
#define SLAP_SYNC_UPDATE_MSGID 1
|
||||
|
||||
struct sync_cookie {
|
||||
struct berval ctxcsn;
|
||||
struct berval *ctxcsn;
|
||||
struct berval octet_str;
|
||||
long rid;
|
||||
int rid;
|
||||
int numcsns;
|
||||
int *sids;
|
||||
LDAP_STAILQ_ENTRY(sync_cookie) sc_next;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,14 @@ struct nonpresent_entry {
|
|||
LDAP_LIST_ENTRY(nonpresent_entry) npe_link;
|
||||
};
|
||||
|
||||
typedef struct cookie_state {
|
||||
ldap_pvt_thread_mutex_t cs_mutex;
|
||||
int cs_num;
|
||||
int cs_age;
|
||||
struct berval *cs_vals;
|
||||
int *cs_sids;
|
||||
} cookie_state;
|
||||
|
||||
#define SYNCDATA_DEFAULT 0 /* entries are plain LDAP entries */
|
||||
#define SYNCDATA_ACCESSLOG 1 /* entries are accesslog format */
|
||||
#define SYNCDATA_CHANGELOG 2 /* entries are changelog format */
|
||||
|
|
@ -50,9 +58,11 @@ struct nonpresent_entry {
|
|||
#define RETRYNUM_FINITE(n) ((n) > RETRYNUM_FOREVER) /* not forever */
|
||||
|
||||
typedef struct syncinfo_s {
|
||||
struct syncinfo_s *si_next;
|
||||
struct slap_backend_db *si_be;
|
||||
struct re_s *si_re;
|
||||
long si_rid;
|
||||
int si_rid;
|
||||
char si_ridtxt[8];
|
||||
slap_bindconf si_bindconf;
|
||||
struct berval si_base;
|
||||
struct berval si_logbase;
|
||||
|
|
@ -75,6 +85,8 @@ typedef struct syncinfo_s {
|
|||
int *si_retrynum_init;
|
||||
int *si_retrynum;
|
||||
struct sync_cookie si_syncCookie;
|
||||
cookie_state *si_cookieState;
|
||||
int si_cookieAge;
|
||||
int si_manageDSAit;
|
||||
int si_slimit;
|
||||
int si_tlimit;
|
||||
|
|
@ -100,8 +112,7 @@ static int syncrepl_message_to_entry(
|
|||
static int syncrepl_entry(
|
||||
syncinfo_t *, Operation*, Entry*,
|
||||
Modifications**,int, struct berval*,
|
||||
struct sync_cookie *,
|
||||
struct berval * );
|
||||
struct sync_cookie * );
|
||||
static int syncrepl_updateCookie(
|
||||
syncinfo_t *, Operation *, struct berval *,
|
||||
struct sync_cookie * );
|
||||
|
|
@ -330,7 +341,7 @@ ldap_sync_search(
|
|||
/* If we're using a log but we have no state, then fallback to
|
||||
* normal mode for a full refresh.
|
||||
*/
|
||||
if ( si->si_syncdata && BER_BVISEMPTY( &si->si_syncCookie.ctxcsn ) ) {
|
||||
if ( si->si_syncdata && !si->si_syncCookie.numcsns ) {
|
||||
si->si_logstate = SYNCLOG_FALLBACK;
|
||||
}
|
||||
|
||||
|
|
@ -417,13 +428,10 @@ do_syncrep1(
|
|||
int cmdline_cookie_found = 0;
|
||||
|
||||
struct sync_cookie *sc = NULL;
|
||||
struct berval *psub;
|
||||
#ifdef HAVE_TLS
|
||||
void *ssl;
|
||||
#endif
|
||||
|
||||
psub = &si->si_be->be_nsuffix[0];
|
||||
|
||||
rc = slap_client_connect( &si->si_ld, &si->si_bindconf );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
goto done;
|
||||
|
|
@ -447,21 +455,43 @@ do_syncrep1(
|
|||
|
||||
|
||||
if ( BER_BVISNULL( &si->si_syncCookie.octet_str ) ) {
|
||||
/* get contextCSN shadow replica from database */
|
||||
BerVarray csn = NULL;
|
||||
int i;
|
||||
|
||||
assert( si->si_rid < 1000 );
|
||||
op->o_req_ndn = op->o_bd->be_nsuffix[0];
|
||||
op->o_req_dn = op->o_req_ndn;
|
||||
ldap_pvt_thread_mutex_lock( &si->si_cookieState->cs_mutex );
|
||||
if ( !si->si_cookieState->cs_num ) {
|
||||
/* get contextCSN shadow replica from database */
|
||||
BerVarray csn = NULL;
|
||||
void *ctx = op->o_tmpmemctx;
|
||||
|
||||
/* try to read stored contextCSN */
|
||||
backend_attribute( op, NULL, &op->o_req_ndn,
|
||||
slap_schema.si_ad_contextCSN, &csn, ACL_READ );
|
||||
if ( csn ) {
|
||||
ch_free( si->si_syncCookie.ctxcsn.bv_val );
|
||||
ber_dupbv( &si->si_syncCookie.ctxcsn, csn );
|
||||
ber_bvarray_free_x( csn, op->o_tmpmemctx );
|
||||
op->o_req_ndn = op->o_bd->be_nsuffix[0];
|
||||
op->o_req_dn = op->o_req_ndn;
|
||||
|
||||
/* try to read stored contextCSN */
|
||||
op->o_tmpmemctx = NULL;
|
||||
backend_attribute( op, NULL, &op->o_req_ndn,
|
||||
slap_schema.si_ad_contextCSN, &csn, ACL_READ );
|
||||
op->o_tmpmemctx = ctx;
|
||||
if ( csn ) {
|
||||
si->si_cookieState->cs_vals = csn;
|
||||
for (i=0; !BER_BVISNULL( &csn[i] ); i++);
|
||||
si->si_cookieState->cs_num = i;
|
||||
si->si_cookieState->cs_sids = slap_parse_csn_sids( csn, i );
|
||||
}
|
||||
}
|
||||
if ( si->si_cookieState->cs_num ) {
|
||||
ber_bvarray_free( si->si_syncCookie.ctxcsn );
|
||||
if ( ber_bvarray_dup_x( &si->si_syncCookie.ctxcsn,
|
||||
si->si_cookieState->cs_vals, NULL )) {
|
||||
rc = LDAP_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
si->si_syncCookie.numcsns = si->si_cookieState->cs_num;
|
||||
si->si_syncCookie.sids = ch_malloc( si->si_cookieState->cs_num *
|
||||
sizeof(int) );
|
||||
for ( i=0; i<si->si_syncCookie.numcsns; i++ )
|
||||
si->si_syncCookie.sids[i] = si->si_cookieState->cs_sids[i];
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &si->si_cookieState->cs_mutex );
|
||||
|
||||
si->si_syncCookie.rid = si->si_rid;
|
||||
|
||||
|
|
@ -479,7 +509,7 @@ do_syncrep1(
|
|||
|
||||
/* ctxcsn wasn't parsed yet, do it now */
|
||||
slap_parse_sync_cookie( sc, op->o_tmpmemctx );
|
||||
if ( BER_BVISNULL( &sc->ctxcsn ) ) {
|
||||
if ( !sc->ctxcsn ) {
|
||||
/* if cmdline cookie does not have ctxcsn */
|
||||
/* component, set it to an initial value */
|
||||
slap_init_sync_cookie_ctxcsn( sc );
|
||||
|
|
@ -490,15 +520,41 @@ do_syncrep1(
|
|||
}
|
||||
|
||||
slap_compose_sync_cookie( NULL, &si->si_syncCookie.octet_str,
|
||||
&si->si_syncCookie.ctxcsn, si->si_syncCookie.rid );
|
||||
si->si_syncCookie.ctxcsn, si->si_syncCookie.rid );
|
||||
} else {
|
||||
ldap_pvt_thread_mutex_lock( &si->si_cookieState->cs_mutex );
|
||||
/* match SIDs */
|
||||
if ( si->si_cookieState->cs_num > 1 && si->si_cookieAge !=
|
||||
si->si_cookieState->cs_age ) {
|
||||
int i, j;
|
||||
|
||||
for (i=0; !BER_BVISNULL( &si->si_syncCookie.ctxcsn[i] ); i++) {
|
||||
/* bogus, just dup everything */
|
||||
if ( si->si_syncCookie.sids[i] == -1 ) {
|
||||
ber_bvarray_free( si->si_syncCookie.ctxcsn );
|
||||
ber_bvarray_dup_x( &si->si_syncCookie.ctxcsn,
|
||||
si->si_cookieState->cs_vals, NULL );
|
||||
break;
|
||||
}
|
||||
for (j=0; j<si->si_cookieState->cs_num; j++) {
|
||||
if ( si->si_syncCookie.sids[i] !=
|
||||
si->si_cookieState->cs_sids[j] )
|
||||
continue;
|
||||
ber_bvreplace( &si->si_syncCookie.ctxcsn[i],
|
||||
&si->si_cookieState->cs_vals[j] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &si->si_cookieState->cs_mutex );
|
||||
}
|
||||
|
||||
rc = ldap_sync_search( si, op->o_tmpmemctx );
|
||||
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY, "do_syncrep1: rid %03ld "
|
||||
Debug( LDAP_DEBUG_ANY, "do_syncrep1: %s "
|
||||
"ldap_search_ext: %s (%d)\n",
|
||||
si->si_rid, ldap_err2string( rc ), rc );
|
||||
si->si_ridtxt, ldap_err2string( rc ), rc );
|
||||
}
|
||||
|
||||
done:
|
||||
|
|
@ -512,6 +568,32 @@ done:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
compare_csns( struct sync_cookie *sc1, struct sync_cookie *sc2, int *which )
|
||||
{
|
||||
int i, j, match = 0;
|
||||
const char *text;
|
||||
|
||||
*which = 0;
|
||||
|
||||
for (i=0; !BER_BVISNULL( &sc1->ctxcsn[i] ); i++) {
|
||||
for (j=0; !BER_BVISNULL( &sc2->ctxcsn[j] ); j++) {
|
||||
if ( sc1->sids[i] != sc2->sids[j] )
|
||||
continue;
|
||||
value_match( &match, slap_schema.si_ad_entryCSN,
|
||||
slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
|
||||
SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
|
||||
&sc1->ctxcsn[i], &sc2->ctxcsn[i], &text );
|
||||
if ( match < 0 ) {
|
||||
*which = j;
|
||||
return match;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
static int
|
||||
do_syncrep2(
|
||||
Operation *op,
|
||||
|
|
@ -533,8 +615,8 @@ do_syncrep2(
|
|||
|
||||
int syncstate;
|
||||
struct berval syncUUID = BER_BVNULL;
|
||||
struct sync_cookie syncCookie = { BER_BVNULL };
|
||||
struct sync_cookie syncCookie_req = { BER_BVNULL };
|
||||
struct sync_cookie syncCookie = { NULL };
|
||||
struct sync_cookie syncCookie_req = { NULL };
|
||||
struct berval cookie = BER_BVNULL;
|
||||
|
||||
int rc, err;
|
||||
|
|
@ -543,8 +625,7 @@ do_syncrep2(
|
|||
struct berval *psub;
|
||||
Modifications *modlist = NULL;
|
||||
|
||||
const char *text;
|
||||
int match;
|
||||
int match, m;
|
||||
|
||||
struct timeval *tout_p = NULL;
|
||||
struct timeval tout = { 0, 0 };
|
||||
|
|
@ -562,7 +643,7 @@ do_syncrep2(
|
|||
ber_init2( ber, NULL, LBER_USE_DER );
|
||||
ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=>do_syncrep2 rid %03ld\n", si->si_rid, 0, 0 );
|
||||
Debug( LDAP_DEBUG_TRACE, "=>do_syncrep2 %s\n", si->si_ridtxt, 0, 0 );
|
||||
|
||||
psub = &si->si_be->be_nsuffix[0];
|
||||
|
||||
|
|
@ -601,9 +682,9 @@ do_syncrep2(
|
|||
rctrlp = ldap_find_control( LDAP_CONTROL_SYNC_STATE, rctrls );
|
||||
}
|
||||
if ( rctrlp == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY, "do_syncrep2: rid %03ld "
|
||||
Debug( LDAP_DEBUG_ANY, "do_syncrep2: %s "
|
||||
"got search entry without "
|
||||
"Sync State control\n", si->si_rid, 0, 0 );
|
||||
"Sync State control\n", si->si_ridtxt, 0, 0 );
|
||||
rc = -1;
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -612,8 +693,8 @@ do_syncrep2(
|
|||
/* FIXME: what if syncUUID is NULL or empty?
|
||||
* (happens with back-sql...) */
|
||||
if ( BER_BVISEMPTY( &syncUUID ) ) {
|
||||
Debug( LDAP_DEBUG_ANY, "do_syncrep2: rid %03ld "
|
||||
"got empty syncUUID\n", si->si_rid, 0, 0 );
|
||||
Debug( LDAP_DEBUG_ANY, "do_syncrep2: %s "
|
||||
"got empty syncUUID\n", si->si_ridtxt, 0, 0 );
|
||||
ldap_controls_free( rctrls );
|
||||
rc = -1;
|
||||
goto done;
|
||||
|
|
@ -633,7 +714,7 @@ do_syncrep2(
|
|||
if ( si->si_syncdata && si->si_logstate == SYNCLOG_LOGGING ) {
|
||||
modlist = NULL;
|
||||
if ( ( rc = syncrepl_message_to_op( si, op, msg ) ) == LDAP_SUCCESS &&
|
||||
!BER_BVISNULL( &syncCookie.ctxcsn ) )
|
||||
syncCookie.ctxcsn )
|
||||
{
|
||||
rc = syncrepl_updateCookie( si, op, psub, &syncCookie );
|
||||
}
|
||||
|
|
@ -641,9 +722,8 @@ do_syncrep2(
|
|||
&modlist, &entry, syncstate ) ) == LDAP_SUCCESS )
|
||||
{
|
||||
if ( ( rc = syncrepl_entry( si, op, entry, &modlist,
|
||||
syncstate, &syncUUID, &syncCookie_req,
|
||||
&syncCookie.ctxcsn ) ) == LDAP_SUCCESS &&
|
||||
!BER_BVISNULL( &syncCookie.ctxcsn ) )
|
||||
syncstate, &syncUUID, &syncCookie_req ) ) == LDAP_SUCCESS &&
|
||||
syncCookie.ctxcsn )
|
||||
{
|
||||
rc = syncrepl_updateCookie( si, op, psub, &syncCookie );
|
||||
}
|
||||
|
|
@ -658,14 +738,14 @@ do_syncrep2(
|
|||
|
||||
case LDAP_RES_SEARCH_REFERENCE:
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"do_syncrep2: rid %03ld reference received error\n",
|
||||
si->si_rid, 0, 0 );
|
||||
"do_syncrep2: %s reference received error\n",
|
||||
si->si_ridtxt, 0, 0 );
|
||||
break;
|
||||
|
||||
case LDAP_RES_SEARCH_RESULT:
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"do_syncrep2: rid %03ld LDAP_RES_SEARCH_RESULT\n",
|
||||
si->si_rid, 0, 0 );
|
||||
"do_syncrep2: %s LDAP_RES_SEARCH_RESULT\n",
|
||||
si->si_ridtxt, 0, 0 );
|
||||
ldap_parse_result( si->si_ld, msg, &err, NULL, NULL, NULL,
|
||||
&rctrls, 0 );
|
||||
#ifdef LDAP_X_SYNC_REFRESH_REQUIRED
|
||||
|
|
@ -703,16 +783,12 @@ do_syncrep2(
|
|||
}
|
||||
ber_scanf( ber, /*"{"*/ "}" );
|
||||
}
|
||||
if ( BER_BVISNULL( &syncCookie_req.ctxcsn ) ) {
|
||||
if ( !syncCookie_req.ctxcsn ) {
|
||||
match = -1;
|
||||
} else if ( BER_BVISNULL( &syncCookie.ctxcsn ) ) {
|
||||
} else if ( !syncCookie.ctxcsn ) {
|
||||
match = 1;
|
||||
} else {
|
||||
value_match( &match, slap_schema.si_ad_entryCSN,
|
||||
slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
|
||||
SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
|
||||
&syncCookie_req.ctxcsn, &syncCookie.ctxcsn,
|
||||
&text );
|
||||
match = compare_csns( &syncCookie_req, &syncCookie, &m );
|
||||
}
|
||||
if ( rctrls ) {
|
||||
ldap_controls_free( rctrls );
|
||||
|
|
@ -725,14 +801,14 @@ do_syncrep2(
|
|||
if ( refreshDeletes == 0 && match < 0 &&
|
||||
err == LDAP_SUCCESS )
|
||||
{
|
||||
syncrepl_del_nonpresent( op, si, NULL, &syncCookie.ctxcsn );
|
||||
syncrepl_del_nonpresent( op, si, NULL,
|
||||
&syncCookie.ctxcsn[m] );
|
||||
} else {
|
||||
avl_free( si->si_presentlist, avl_ber_bvfree );
|
||||
si->si_presentlist = NULL;
|
||||
}
|
||||
}
|
||||
if ( !BER_BVISNULL( &syncCookie.ctxcsn ) &&
|
||||
match < 0 && err == LDAP_SUCCESS )
|
||||
if ( syncCookie.ctxcsn && match < 0 && err == LDAP_SUCCESS )
|
||||
{
|
||||
rc = syncrepl_updateCookie( si, op, psub, &syncCookie );
|
||||
}
|
||||
|
|
@ -756,8 +832,8 @@ do_syncrep2(
|
|||
ber_tag_t tag;
|
||||
case LDAP_TAG_SYNC_NEW_COOKIE:
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"do_syncrep2: rid %03ld %s - %s\n",
|
||||
si->si_rid,
|
||||
"do_syncrep2: %s %s - %s\n",
|
||||
si->si_ridtxt,
|
||||
"LDAP_RES_INTERMEDIATE",
|
||||
"NEW_COOKIE" );
|
||||
ber_scanf( ber, "tm", &tag, &cookie );
|
||||
|
|
@ -765,8 +841,8 @@ do_syncrep2(
|
|||
case LDAP_TAG_SYNC_REFRESH_DELETE:
|
||||
case LDAP_TAG_SYNC_REFRESH_PRESENT:
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"do_syncrep2: rid %03ld %s - %s\n",
|
||||
si->si_rid,
|
||||
"do_syncrep2: %s %s - %s\n",
|
||||
si->si_ridtxt,
|
||||
"LDAP_RES_INTERMEDIATE",
|
||||
si_tag == LDAP_TAG_SYNC_REFRESH_PRESENT ?
|
||||
"REFRESH_PRESENT" : "REFRESH_DELETE" );
|
||||
|
|
@ -797,8 +873,8 @@ do_syncrep2(
|
|||
break;
|
||||
case LDAP_TAG_SYNC_ID_SET:
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"do_syncrep2: rid %03ld %s - %s\n",
|
||||
si->si_rid,
|
||||
"do_syncrep2: %s %s - %s\n",
|
||||
si->si_ridtxt,
|
||||
"LDAP_RES_INTERMEDIATE",
|
||||
"SYNC_ID_SET" );
|
||||
ber_scanf( ber, "t{" /*"}"*/, &tag );
|
||||
|
|
@ -813,6 +889,7 @@ do_syncrep2(
|
|||
if ( !BER_BVISNULL( &syncCookie.octet_str ) )
|
||||
{
|
||||
slap_parse_sync_cookie( &syncCookie, NULL );
|
||||
compare_csns( &syncCookie_req, &syncCookie, &m );
|
||||
}
|
||||
}
|
||||
if ( ber_peek_tag( ber, &len ) ==
|
||||
|
|
@ -824,7 +901,7 @@ do_syncrep2(
|
|||
ber_scanf( ber, /*"{"*/ "}" );
|
||||
if ( refreshDeletes ) {
|
||||
syncrepl_del_nonpresent( op, si, syncUUIDs,
|
||||
&syncCookie.ctxcsn );
|
||||
&syncCookie.ctxcsn[m] );
|
||||
ber_bvarray_free_x( syncUUIDs, op->o_tmpmemctx );
|
||||
} else {
|
||||
int i;
|
||||
|
|
@ -845,31 +922,28 @@ do_syncrep2(
|
|||
break;
|
||||
default:
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"do_syncrep2: rid %03ld unknown syncinfo tag (%ld)\n",
|
||||
si->si_rid, (long) si_tag, 0 );
|
||||
"do_syncrep2: %s unknown syncinfo tag (%ld)\n",
|
||||
si->si_ridtxt, (long) si_tag, 0 );
|
||||
ldap_memfree( retoid );
|
||||
ber_bvfree( retdata );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( BER_BVISNULL( &syncCookie_req.ctxcsn ) ) {
|
||||
if ( !syncCookie_req.ctxcsn ) {
|
||||
match = -1;
|
||||
} else if ( BER_BVISNULL( &syncCookie.ctxcsn ) ) {
|
||||
} else if ( !syncCookie.ctxcsn ) {
|
||||
match = 1;
|
||||
} else {
|
||||
value_match( &match, slap_schema.si_ad_entryCSN,
|
||||
slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
|
||||
SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
|
||||
&syncCookie_req.ctxcsn,
|
||||
&syncCookie.ctxcsn, &text );
|
||||
match = compare_csns( &syncCookie_req, &syncCookie, &m );
|
||||
}
|
||||
|
||||
if ( match < 0 ) {
|
||||
if ( si->si_refreshPresent == 1 ) {
|
||||
syncrepl_del_nonpresent( op, si, NULL, &syncCookie.ctxcsn );
|
||||
syncrepl_del_nonpresent( op, si, NULL,
|
||||
&syncCookie.ctxcsn[m] );
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &syncCookie.ctxcsn ) )
|
||||
if ( syncCookie.ctxcsn )
|
||||
{
|
||||
rc = syncrepl_updateCookie( si, op, psub, &syncCookie);
|
||||
}
|
||||
|
|
@ -880,9 +954,9 @@ do_syncrep2(
|
|||
break;
|
||||
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_ANY, "do_syncrep2: rid %03ld "
|
||||
Debug( LDAP_DEBUG_ANY, "do_syncrep2: %s "
|
||||
"unknown intermediate response (%d)\n",
|
||||
si->si_rid, rc, 0 );
|
||||
si->si_ridtxt, rc, 0 );
|
||||
ldap_memfree( retoid );
|
||||
ber_bvfree( retdata );
|
||||
break;
|
||||
|
|
@ -890,8 +964,8 @@ do_syncrep2(
|
|||
break;
|
||||
|
||||
default:
|
||||
Debug( LDAP_DEBUG_ANY, "do_syncrep2: rid %03ld "
|
||||
"unknown message\n", si->si_rid, 0, 0 );
|
||||
Debug( LDAP_DEBUG_ANY, "do_syncrep2: %s "
|
||||
"unknown message\n", si->si_ridtxt, 0, 0 );
|
||||
break;
|
||||
|
||||
}
|
||||
|
|
@ -912,7 +986,7 @@ do_syncrep2(
|
|||
errstr = ldap_err2string( rc );
|
||||
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"do_syncrep2: rid %03ld %s\n", si->si_rid, errstr, 0 );
|
||||
"do_syncrep2: %s %s\n", si->si_ridtxt, errstr, 0 );
|
||||
}
|
||||
|
||||
done:
|
||||
|
|
@ -951,7 +1025,7 @@ do_syncrepl(
|
|||
int i, defer = 1;
|
||||
Backend *be;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=>do_syncrepl rid %03ld\n", si->si_rid, 0, 0 );
|
||||
Debug( LDAP_DEBUG_TRACE, "=>do_syncrepl %s\n", si->si_ridtxt, 0, 0 );
|
||||
|
||||
if ( si == NULL )
|
||||
return NULL;
|
||||
|
|
@ -1201,9 +1275,9 @@ syncrepl_message_to_op(
|
|||
int rc, deleteOldRdn = 0, freeReqDn = 0;
|
||||
|
||||
if ( ldap_msgtype( msg ) != LDAP_RES_SEARCH_ENTRY ) {
|
||||
Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_op: rid %03ld "
|
||||
Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_op: %s "
|
||||
"Message type should be entry (%d)",
|
||||
si->si_rid, ldap_msgtype( msg ), 0 );
|
||||
si->si_ridtxt, ldap_msgtype( msg ), 0 );
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -1216,8 +1290,8 @@ syncrepl_message_to_op(
|
|||
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"syncrepl_message_to_op: rid %03ld dn get failed (%d)",
|
||||
si->si_rid, rc, 0 );
|
||||
"syncrepl_message_to_op: %s dn get failed (%d)",
|
||||
si->si_ridtxt, rc, 0 );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -1240,8 +1314,8 @@ syncrepl_message_to_op(
|
|||
int i = verb_to_mask( bvals[0].bv_val, modops );
|
||||
if ( i < 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"syncrepl_message_to_op: rid %03ld unknown op %s",
|
||||
si->si_rid, bvals[0].bv_val, 0 );
|
||||
"syncrepl_message_to_op: %s unknown op %s",
|
||||
si->si_ridtxt, bvals[0].bv_val, 0 );
|
||||
ch_free( bvals );
|
||||
rc = -1;
|
||||
goto done;
|
||||
|
|
@ -1288,9 +1362,9 @@ syncrepl_message_to_op(
|
|||
rc = slap_mods_check( op, modlist, &text, txtbuf, textlen, NULL );
|
||||
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_op: rid %03ld "
|
||||
Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_op: %s "
|
||||
"mods check (%s)\n",
|
||||
si->si_rid, text, 0 );
|
||||
si->si_ridtxt, text, 0 );
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
|
@ -1302,14 +1376,14 @@ syncrepl_message_to_op(
|
|||
freeReqDn = 0;
|
||||
rc = slap_mods2entry( modlist, &op->ora_e, 1, 0, &text, txtbuf, textlen);
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_op: rid %03ld "
|
||||
Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_op: %s "
|
||||
"mods2entry (%s)\n",
|
||||
si->si_rid, text, 0 );
|
||||
si->si_ridtxt, text, 0 );
|
||||
} else {
|
||||
rc = op->o_bd->be_add( op, &rs );
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"syncrepl_message_to_op: rid %03ld be_add %s (%d)\n",
|
||||
si->si_rid, op->o_req_dn.bv_val, rc );
|
||||
"syncrepl_message_to_op: %s be_add %s (%d)\n",
|
||||
si->si_ridtxt, op->o_req_dn.bv_val, rc );
|
||||
}
|
||||
if ( e == op->ora_e )
|
||||
be_entry_release_w( op, op->ora_e );
|
||||
|
|
@ -1317,8 +1391,8 @@ syncrepl_message_to_op(
|
|||
op->orm_modlist = modlist;
|
||||
rc = op->o_bd->be_modify( op, &rs );
|
||||
Debug( rc ? LDAP_DEBUG_ANY : LDAP_DEBUG_SYNC,
|
||||
"syncrepl_message_to_op: rid %03ld be_modify %s (%d)\n",
|
||||
si->si_rid, op->o_req_dn.bv_val, rc );
|
||||
"syncrepl_message_to_op: %s be_modify %s (%d)\n",
|
||||
si->si_ridtxt, op->o_req_dn.bv_val, rc );
|
||||
}
|
||||
break;
|
||||
case LDAP_REQ_MODRDN:
|
||||
|
|
@ -1360,14 +1434,14 @@ syncrepl_message_to_op(
|
|||
rc = op->o_bd->be_modrdn( op, &rs );
|
||||
slap_mods_free( op->orr_modlist, 1 );
|
||||
Debug( rc ? LDAP_DEBUG_ANY : LDAP_DEBUG_SYNC,
|
||||
"syncrepl_message_to_op: rid %03ld be_modrdn %s (%d)\n",
|
||||
si->si_rid, op->o_req_dn.bv_val, rc );
|
||||
"syncrepl_message_to_op: %s be_modrdn %s (%d)\n",
|
||||
si->si_ridtxt, op->o_req_dn.bv_val, rc );
|
||||
break;
|
||||
case LDAP_REQ_DELETE:
|
||||
rc = op->o_bd->be_delete( op, &rs );
|
||||
Debug( rc ? LDAP_DEBUG_ANY : LDAP_DEBUG_SYNC,
|
||||
"syncrepl_message_to_op: rid %03ld be_delete %s (%d)\n",
|
||||
si->si_rid, op->o_req_dn.bv_val, rc );
|
||||
"syncrepl_message_to_op: %s be_delete %s (%d)\n",
|
||||
si->si_ridtxt, op->o_req_dn.bv_val, rc );
|
||||
break;
|
||||
}
|
||||
done:
|
||||
|
|
@ -1425,9 +1499,9 @@ syncrepl_message_to_entry(
|
|||
*modlist = NULL;
|
||||
|
||||
if ( ldap_msgtype( msg ) != LDAP_RES_SEARCH_ENTRY ) {
|
||||
Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: rid %03ld "
|
||||
Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: %s "
|
||||
"Message type should be entry (%d)",
|
||||
si->si_rid, ldap_msgtype( msg ), 0 );
|
||||
si->si_ridtxt, ldap_msgtype( msg ), 0 );
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -1436,8 +1510,8 @@ syncrepl_message_to_entry(
|
|||
rc = ldap_get_dn_ber( si->si_ld, msg, &ber, &bdn );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"syncrepl_message_to_entry: rid %03ld dn get failed (%d)",
|
||||
si->si_rid, rc, 0 );
|
||||
"syncrepl_message_to_entry: %s dn get failed (%d)",
|
||||
si->si_ridtxt, rc, 0 );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -1485,8 +1559,8 @@ syncrepl_message_to_entry(
|
|||
}
|
||||
|
||||
if ( *modlist == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: rid %03ld no attributes\n",
|
||||
si->si_rid, 0, 0 );
|
||||
Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: %s no attributes\n",
|
||||
si->si_ridtxt, 0, 0 );
|
||||
rc = -1;
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -1494,8 +1568,8 @@ syncrepl_message_to_entry(
|
|||
rc = slap_mods_check( op, *modlist, &text, txtbuf, textlen, NULL );
|
||||
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: rid %03ld mods check (%s)\n",
|
||||
si->si_rid, text, 0 );
|
||||
Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: %s mods check (%s)\n",
|
||||
si->si_ridtxt, text, 0 );
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
|
@ -1527,8 +1601,8 @@ syncrepl_message_to_entry(
|
|||
|
||||
rc = slap_mods2entry( *modlist, &e, 1, 1, &text, txtbuf, textlen);
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: rid %03ld mods2entry (%s)\n",
|
||||
si->si_rid, text, 0 );
|
||||
Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: %s mods2entry (%s)\n",
|
||||
si->si_ridtxt, text, 0 );
|
||||
}
|
||||
|
||||
done:
|
||||
|
|
@ -1583,8 +1657,7 @@ syncrepl_entry(
|
|||
Modifications** modlist,
|
||||
int syncstate,
|
||||
struct berval* syncUUID,
|
||||
struct sync_cookie* syncCookie_req,
|
||||
struct berval* syncCSN )
|
||||
struct sync_cookie* syncCookie_req )
|
||||
{
|
||||
Backend *be = op->o_bd;
|
||||
slap_callback cb = { NULL, NULL, NULL, NULL };
|
||||
|
|
@ -1610,28 +1683,28 @@ syncrepl_entry(
|
|||
|
||||
switch( syncstate ) {
|
||||
case LDAP_SYNC_PRESENT:
|
||||
Debug( LDAP_DEBUG_SYNC, "syncrepl_entry: rid %03ld %s\n",
|
||||
si->si_rid,
|
||||
Debug( LDAP_DEBUG_SYNC, "syncrepl_entry: %s %s\n",
|
||||
si->si_ridtxt,
|
||||
"LDAP_RES_SEARCH_ENTRY(LDAP_SYNC_PRESENT)", 0 );
|
||||
break;
|
||||
case LDAP_SYNC_ADD:
|
||||
Debug( LDAP_DEBUG_SYNC, "syncrepl_entry: rid %03ld %s\n",
|
||||
si->si_rid,
|
||||
Debug( LDAP_DEBUG_SYNC, "syncrepl_entry: %s %s\n",
|
||||
si->si_ridtxt,
|
||||
"LDAP_RES_SEARCH_ENTRY(LDAP_SYNC_ADD)", 0 );
|
||||
break;
|
||||
case LDAP_SYNC_DELETE:
|
||||
Debug( LDAP_DEBUG_SYNC, "syncrepl_entry: rid %03ld %s\n",
|
||||
si->si_rid,
|
||||
Debug( LDAP_DEBUG_SYNC, "syncrepl_entry: %s %s\n",
|
||||
si->si_ridtxt,
|
||||
"LDAP_RES_SEARCH_ENTRY(LDAP_SYNC_DELETE)", 0 );
|
||||
break;
|
||||
case LDAP_SYNC_MODIFY:
|
||||
Debug( LDAP_DEBUG_SYNC, "syncrepl_entry: rid %03ld %s\n",
|
||||
si->si_rid,
|
||||
Debug( LDAP_DEBUG_SYNC, "syncrepl_entry: %s %s\n",
|
||||
si->si_ridtxt,
|
||||
"LDAP_RES_SEARCH_ENTRY(LDAP_SYNC_MODIFY)", 0 );
|
||||
break;
|
||||
default:
|
||||
Debug( LDAP_DEBUG_ANY, "syncrepl_entry: rid %03ld %s\n",
|
||||
si->si_rid,
|
||||
Debug( LDAP_DEBUG_ANY, "syncrepl_entry: %s %s\n",
|
||||
si->si_ridtxt,
|
||||
"LDAP_RES_SEARCH_ENTRY(UNKNOWN syncstate)", 0 );
|
||||
}
|
||||
|
||||
|
|
@ -1681,8 +1754,8 @@ syncrepl_entry(
|
|||
ava.aa_value = *syncUUID;
|
||||
|
||||
if ( syncuuid_bv ) {
|
||||
Debug( LDAP_DEBUG_SYNC, "syncrepl_entry: rid %03ld inserted UUID %s\n",
|
||||
si->si_rid, syncUUID_strrep.bv_val, 0 );
|
||||
Debug( LDAP_DEBUG_SYNC, "syncrepl_entry: %s inserted UUID %s\n",
|
||||
si->si_ridtxt, syncUUID_strrep.bv_val, 0 );
|
||||
}
|
||||
op->ors_filter = &f;
|
||||
|
||||
|
|
@ -1720,8 +1793,8 @@ syncrepl_entry(
|
|||
if ( limits_check( op, &rs_search ) == 0 ) {
|
||||
rc = be->be_search( op, &rs_search );
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"syncrepl_entry: rid %03ld be_search (%d)\n",
|
||||
si->si_rid, rc, 0 );
|
||||
"syncrepl_entry: %s be_search (%d)\n",
|
||||
si->si_ridtxt, rc, 0 );
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &op->ors_filterstr ) ) {
|
||||
|
|
@ -1733,12 +1806,12 @@ syncrepl_entry(
|
|||
|
||||
if ( entry && !BER_BVISNULL( &entry->e_name ) ) {
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"syncrepl_entry: rid %03ld %s\n",
|
||||
si->si_rid, entry->e_name.bv_val, 0 );
|
||||
"syncrepl_entry: %s %s\n",
|
||||
si->si_ridtxt, entry->e_name.bv_val, 0 );
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"syncrepl_entry: rid %03ld %s\n",
|
||||
si->si_rid, dni.dn.bv_val ? dni.dn.bv_val : "(null)", 0 );
|
||||
"syncrepl_entry: %s %s\n",
|
||||
si->si_ridtxt, dni.dn.bv_val ? dni.dn.bv_val : "(null)", 0 );
|
||||
}
|
||||
|
||||
/* Don't save the contextCSN on the inooming context entry,
|
||||
|
|
@ -1785,8 +1858,8 @@ retry_add:;
|
|||
|
||||
rc = be->be_add( op, &rs_add );
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"syncrepl_entry: rid %03ld be_add (%d)\n",
|
||||
si->si_rid, rc, 0 );
|
||||
"syncrepl_entry: %s be_add (%d)\n",
|
||||
si->si_ridtxt, rc, 0 );
|
||||
switch ( rs_add.sr_err ) {
|
||||
case LDAP_SUCCESS:
|
||||
if ( op->ora_e == entry ) {
|
||||
|
|
@ -1847,8 +1920,8 @@ retry_add:;
|
|||
|
||||
default:
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"syncrepl_entry: rid %03ld be_add failed (%d)\n",
|
||||
si->si_rid, rs_add.sr_err, 0 );
|
||||
"syncrepl_entry: %s be_add failed (%d)\n",
|
||||
si->si_ridtxt, rs_add.sr_err, 0 );
|
||||
break;
|
||||
}
|
||||
goto done;
|
||||
|
|
@ -1923,8 +1996,8 @@ retry_add:;
|
|||
|
||||
slap_mods_free( op->orr_modlist, 1 );
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"syncrepl_entry: rid %03ld be_modrdn (%d)\n",
|
||||
si->si_rid, rc, 0 );
|
||||
"syncrepl_entry: %s be_modrdn (%d)\n",
|
||||
si->si_ridtxt, rc, 0 );
|
||||
goto done;
|
||||
}
|
||||
if ( dni.mods ) {
|
||||
|
|
@ -1935,17 +2008,17 @@ retry_add:;
|
|||
rc = be->be_modify( op, &rs_modify );
|
||||
slap_mods_free( op->orm_modlist, 1 );
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"syncrepl_entry: rid %03ld be_modify (%d)\n",
|
||||
si->si_rid, rc, 0 );
|
||||
"syncrepl_entry: %s be_modify (%d)\n",
|
||||
si->si_ridtxt, rc, 0 );
|
||||
if ( rs_modify.sr_err != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"syncrepl_entry: rid %03ld be_modify failed (%d)\n",
|
||||
si->si_rid, rs_modify.sr_err, 0 );
|
||||
"syncrepl_entry: %s be_modify failed (%d)\n",
|
||||
si->si_ridtxt, rs_modify.sr_err, 0 );
|
||||
}
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"syncrepl_entry: rid %03ld entry unchanged, ignored (%s)\n",
|
||||
si->si_rid, op->o_req_dn.bv_val, 0 );
|
||||
"syncrepl_entry: %s entry unchanged, ignored (%s)\n",
|
||||
si->si_ridtxt, op->o_req_dn.bv_val, 0 );
|
||||
}
|
||||
goto done;
|
||||
case LDAP_SYNC_DELETE :
|
||||
|
|
@ -1955,8 +2028,8 @@ retry_add:;
|
|||
op->o_tag = LDAP_REQ_DELETE;
|
||||
rc = be->be_delete( op, &rs_delete );
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"syncrepl_entry: rid %03ld be_delete (%d)\n",
|
||||
si->si_rid, rc, 0 );
|
||||
"syncrepl_entry: %s be_delete (%d)\n",
|
||||
si->si_ridtxt, rc, 0 );
|
||||
|
||||
while ( rs_delete.sr_err == LDAP_SUCCESS
|
||||
&& op->o_delete_glue_parent ) {
|
||||
|
|
@ -1978,7 +2051,7 @@ retry_add:;
|
|||
|
||||
default :
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"syncrepl_entry: rid %03ld unknown syncstate\n", si->si_rid, 0, 0 );
|
||||
"syncrepl_entry: %s unknown syncstate\n", si->si_ridtxt, 0, 0 );
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
|
@ -2095,7 +2168,7 @@ syncrepl_del_nonpresent(
|
|||
if ( cookiecsn && !BER_BVISNULL( cookiecsn ) ) {
|
||||
csn = *cookiecsn;
|
||||
} else {
|
||||
csn = si->si_syncCookie.ctxcsn;
|
||||
csn = si->si_syncCookie.ctxcsn[0];
|
||||
}
|
||||
|
||||
slap_queue_csn( op, &csn );
|
||||
|
|
@ -2113,8 +2186,8 @@ syncrepl_del_nonpresent(
|
|||
op->o_req_ndn = *np_prev->npe_nname;
|
||||
rc = op->o_bd->be_delete( op, &rs_delete );
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"syncrepl_del_nonpresent: rid %03ld be_delete %s (%d)\n",
|
||||
si->si_rid, op->o_req_dn.bv_val, rc );
|
||||
"syncrepl_del_nonpresent: %s be_delete %s (%d)\n",
|
||||
si->si_ridtxt, op->o_req_dn.bv_val, rc );
|
||||
|
||||
if ( rs_delete.sr_err == LDAP_NOT_ALLOWED_ON_NONLEAF ) {
|
||||
Modifications mod1, mod2;
|
||||
|
|
@ -2329,27 +2402,57 @@ syncrepl_updateCookie(
|
|||
struct sync_cookie *syncCookie )
|
||||
{
|
||||
Backend *be = op->o_bd;
|
||||
Modifications mod = { { 0 } };
|
||||
struct berval vals[ 2 ];
|
||||
Modifications mod[2];
|
||||
struct berval first = BER_BVNULL;
|
||||
|
||||
int rc, flags;
|
||||
int rc, i, j;
|
||||
|
||||
slap_callback cb = { NULL };
|
||||
SlapReply rs_modify = {REP_RESULT};
|
||||
|
||||
mod.sml_op = LDAP_MOD_REPLACE;
|
||||
mod.sml_desc = slap_schema.si_ad_contextCSN;
|
||||
mod.sml_type = mod.sml_desc->ad_cname;
|
||||
mod.sml_values = vals;
|
||||
vals[0] = syncCookie->ctxcsn;
|
||||
BER_BVZERO( &vals[1] );
|
||||
mod[0].sml_op = LDAP_MOD_DELETE;
|
||||
mod[0].sml_desc = slap_schema.si_ad_contextCSN;
|
||||
mod[0].sml_type = mod[0].sml_desc->ad_cname;
|
||||
mod[0].sml_values = NULL;
|
||||
mod[0].sml_nvalues = NULL;
|
||||
mod[0].sml_next = &mod[1];
|
||||
|
||||
slap_queue_csn( op, &syncCookie->ctxcsn );
|
||||
mod[1].sml_op = LDAP_MOD_ADD;
|
||||
mod[1].sml_desc = slap_schema.si_ad_contextCSN;
|
||||
mod[1].sml_type = mod[0].sml_desc->ad_cname;
|
||||
mod[1].sml_values = NULL;
|
||||
mod[1].sml_nvalues = NULL;
|
||||
mod[1].sml_next = NULL;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &si->si_cookieState->cs_mutex );
|
||||
|
||||
for ( i=0; i<syncCookie->numcsns; i++ ) {
|
||||
for ( j=0; j<si->si_cookieState->cs_num; j++ ) {
|
||||
if ( syncCookie->sids[i] != si->si_cookieState->cs_sids[j] )
|
||||
continue;
|
||||
if ( ber_bvcmp( &syncCookie->ctxcsn[i],
|
||||
&si->si_cookieState->cs_vals[j] ) > 0 ) {
|
||||
ber_bvarray_add_x( &mod[0].sml_values,
|
||||
&si->si_cookieState->cs_vals[j], op->o_tmpmemctx );
|
||||
ber_bvarray_add_x( &mod[1].sml_values,
|
||||
&syncCookie->ctxcsn[i], op->o_tmpmemctx );
|
||||
if ( BER_BVISNULL( &first ))
|
||||
first = syncCookie->ctxcsn[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* there was no match for this SID, it's a new CSN */
|
||||
if ( j == si->si_cookieState->cs_num ) {
|
||||
ber_bvarray_add_x( &mod[1].sml_values,
|
||||
&syncCookie->ctxcsn[i], op->o_tmpmemctx );
|
||||
if ( BER_BVISNULL( &first ))
|
||||
first = syncCookie->ctxcsn[i];
|
||||
}
|
||||
}
|
||||
slap_queue_csn( op, &first );
|
||||
|
||||
op->o_tag = LDAP_REQ_MODIFY;
|
||||
|
||||
assert( si->si_rid < 1000 );
|
||||
|
||||
cb.sc_response = null_callback;
|
||||
cb.sc_private = si;
|
||||
|
||||
|
|
@ -2359,26 +2462,55 @@ syncrepl_updateCookie(
|
|||
|
||||
/* update contextCSN */
|
||||
op->o_msgid = SLAP_SYNC_UPDATE_MSGID;
|
||||
op->orm_modlist = &mod;
|
||||
flags = SLAP_DBFLAGS( op->o_bd );
|
||||
SLAP_DBFLAGS( op->o_bd ) |= SLAP_DBFLAG_NOLASTMOD;
|
||||
|
||||
if ( mod[0].sml_values )
|
||||
op->orm_modlist = mod;
|
||||
else
|
||||
op->orm_modlist = &mod[1];
|
||||
|
||||
op->orm_no_opattrs = 1;
|
||||
rc = be->be_modify( op, &rs_modify );
|
||||
SLAP_DBFLAGS( op->o_bd ) = flags;
|
||||
op->o_msgid = 0;
|
||||
|
||||
if ( rs_modify.sr_err == LDAP_SUCCESS ) {
|
||||
slap_sync_cookie_free( &si->si_syncCookie, 0 );
|
||||
slap_dup_sync_cookie( &si->si_syncCookie, syncCookie );
|
||||
/* If we replaced any old values */
|
||||
if ( mod[0].sml_values ) {
|
||||
for ( i=0; !BER_BVISNULL( &mod[0].sml_values[i] ); i++ ) {
|
||||
for ( j=0; j<si->si_cookieState->cs_num; j++ ) {
|
||||
if ( mod[0].sml_values[i].bv_val !=
|
||||
si->si_cookieState->cs_vals[j].bv_val )
|
||||
continue;
|
||||
ber_bvreplace( &si->si_cookieState->cs_vals[j],
|
||||
&mod[1].sml_values[i] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Else we just added */
|
||||
si->si_cookieState->cs_num += syncCookie->numcsns;
|
||||
value_add( &si->si_cookieState->cs_vals, syncCookie->ctxcsn );
|
||||
free( si->si_cookieState->cs_sids );
|
||||
si->si_cookieState->cs_sids = slap_parse_csn_sids(
|
||||
si->si_cookieState->cs_vals, si->si_cookieState->cs_num );
|
||||
}
|
||||
|
||||
si->si_cookieState->cs_age++;
|
||||
si->si_cookieAge = si->si_cookieState->cs_age;
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"syncrepl_updateCookie: rid %03ld be_modify failed (%d)\n",
|
||||
si->si_rid, rs_modify.sr_err, 0 );
|
||||
"syncrepl_updateCookie: %s be_modify failed (%d)\n",
|
||||
si->si_ridtxt, rs_modify.sr_err, 0 );
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &si->si_cookieState->cs_mutex );
|
||||
|
||||
slap_graduate_commit_csn( op );
|
||||
op->o_tmpfree( op->o_csn.bv_val, op->o_tmpmemctx );
|
||||
BER_BVZERO( &op->o_csn );
|
||||
if ( mod.sml_next ) slap_mods_free( mod.sml_next, 1 );
|
||||
if ( mod[1].sml_next ) slap_mods_free( mod[1].sml_next, 1 );
|
||||
op->o_tmpfree( mod[1].sml_values, op->o_tmpmemctx );
|
||||
op->o_tmpfree( mod[0].sml_values, op->o_tmpmemctx );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -2662,7 +2794,7 @@ nonpresent_callback(
|
|||
|
||||
} else if ( rs->sr_type == REP_SEARCH ) {
|
||||
if ( !( si->si_refreshDelete & NP_DELETE_ONE ) ) {
|
||||
char buf[sizeof("000 not")];
|
||||
char buf[sizeof("rid=000 not")];
|
||||
|
||||
a = attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_entryUUID );
|
||||
|
||||
|
|
@ -2672,11 +2804,11 @@ nonpresent_callback(
|
|||
}
|
||||
|
||||
if ( slap_debug & LDAP_DEBUG_SYNC ) {
|
||||
sprintf( buf, "%03ld %s", si->si_rid,
|
||||
sprintf( buf, "%s %s", si->si_ridtxt,
|
||||
present_uuid ? "got" : "not" );
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_SYNC, "nonpresent_callback: rid %s UUID %s, dn %s\n",
|
||||
Debug( LDAP_DEBUG_SYNC, "nonpresent_callback: %s UUID %s, dn %s\n",
|
||||
buf, a ? a->a_vals[0].bv_val : "<missing>", rs->sr_entry->e_name.bv_val );
|
||||
|
||||
if ( a == NULL ) return 0;
|
||||
|
|
@ -2992,6 +3124,7 @@ parse_syncrepl_line(
|
|||
return -1;
|
||||
}
|
||||
si->si_rid = tmp;
|
||||
sprintf( si->si_ridtxt, IDSTR "=%03d", si->si_rid );
|
||||
gots |= GOT_ID;
|
||||
} else if ( !strncasecmp( c->argv[ i ], PROVIDERSTR "=",
|
||||
STRLENOF( PROVIDERSTR "=" ) ) )
|
||||
|
|
@ -3468,7 +3601,7 @@ add_syncrepl(
|
|||
init_syncrepl( si );
|
||||
si->si_re = ldap_pvt_runqueue_insert( &slapd_rq,
|
||||
si->si_interval, do_syncrepl, si, "do_syncrepl",
|
||||
c->be->be_suffix[0].bv_val );
|
||||
si->si_ridtxt );
|
||||
if ( si->si_re )
|
||||
rc = config_sync_shadow( c ) ? -1 : 0;
|
||||
else
|
||||
|
|
@ -3493,6 +3626,13 @@ add_syncrepl(
|
|||
if ( !si->si_schemachecking ) {
|
||||
SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_NO_SCHEMA_CHECK;
|
||||
}
|
||||
if ( c->be->be_syncinfo ) {
|
||||
si->si_cookieState = c->be->be_syncinfo->si_cookieState;
|
||||
} else {
|
||||
si->si_cookieState = ch_calloc( 1, sizeof( cookie_state ));
|
||||
ldap_pvt_thread_mutex_init( &si->si_cookieState->cs_mutex );
|
||||
}
|
||||
si->si_next = c->be->be_syncinfo;
|
||||
c->be->be_syncinfo = si;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -3667,20 +3807,43 @@ syncrepl_config( ConfigArgs *c )
|
|||
if (c->op == SLAP_CONFIG_EMIT) {
|
||||
if ( c->be->be_syncinfo ) {
|
||||
struct berval bv;
|
||||
syncrepl_unparse( c->be->be_syncinfo, &bv );
|
||||
ber_bvarray_add( &c->rvalue_vals, &bv );
|
||||
syncinfo_t *si;
|
||||
|
||||
for ( si = c->be->be_syncinfo; si; si=si->si_next ) {
|
||||
syncrepl_unparse( si, &bv );
|
||||
ber_bvarray_add( &c->rvalue_vals, &bv );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
} else if ( c->op == LDAP_MOD_DELETE ) {
|
||||
cookie_state *cs = NULL;
|
||||
if ( c->be->be_syncinfo ) {
|
||||
syncinfo_free( c->be->be_syncinfo );
|
||||
c->be->be_syncinfo = NULL;
|
||||
syncinfo_t *si, **sip;
|
||||
int i;
|
||||
|
||||
cs = c->be->be_syncinfo->si_cookieState;
|
||||
for ( sip = &c->be->be_syncinfo, i=0; *sip; i++ ) {
|
||||
si = *sip;
|
||||
if ( c->valx == -1 || i == c->valx ) {
|
||||
*sip = si->si_next;
|
||||
syncinfo_free( si );
|
||||
} else {
|
||||
sip = &si->si_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( !c->be->be_syncinfo ) {
|
||||
SLAP_DBFLAGS( c->be ) &= ~(SLAP_DBFLAG_SHADOW|SLAP_DBFLAG_SYNC_SHADOW);
|
||||
if ( cs ) {
|
||||
ber_bvarray_free( cs->cs_vals );
|
||||
ldap_pvt_thread_mutex_destroy( &cs->cs_mutex );
|
||||
ch_free( cs );
|
||||
}
|
||||
}
|
||||
SLAP_DBFLAGS( c->be ) &= ~(SLAP_DBFLAG_SHADOW|SLAP_DBFLAG_SYNC_SHADOW);
|
||||
return 0;
|
||||
}
|
||||
if ( SLAP_SHADOW( c->be ) ) {
|
||||
if ( SLAP_SLURP_SHADOW( c->be ) ) {
|
||||
Debug(LDAP_DEBUG_ANY, "%s: "
|
||||
"syncrepl: database already shadowed.\n",
|
||||
c->log, 0, 0);
|
||||
|
|
|
|||
Loading…
Reference in a new issue