mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-04-12 15:10:31 +08:00
syncrepl consistency patch
This commit is contained in:
parent
baa76b6f35
commit
4efd705cc3
@ -96,6 +96,7 @@ LDAP_BEGIN_DECL
|
||||
#define LDAP_DEBUG_PARSE 0x0800
|
||||
#define LDAP_DEBUG_CACHE 0x1000
|
||||
#define LDAP_DEBUG_INDEX 0x2000
|
||||
#define LDAP_DEBUG_SYNC 0x4000
|
||||
|
||||
#define LDAP_DEBUG_NONE 0x8000
|
||||
#define LDAP_DEBUG_ANY -1
|
||||
|
@ -366,6 +366,17 @@ retry: /* transaction retry */
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_rdwr_wlock( &bdb->bi_pslist_rwlock );
|
||||
LDAP_LIST_FOREACH( ps_list, &bdb->bi_psearch_list, o_ps_link ) {
|
||||
rc = bdb_psearch( op, rs, ps_list, e, LDAP_PSEARCH_BY_PREDELETE );
|
||||
if ( rc ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"bdb_delete: persistent search failed (%d,%d)\n",
|
||||
rc, rs->sr_err, 0 );
|
||||
}
|
||||
}
|
||||
ldap_pvt_thread_rdwr_wunlock( &bdb->bi_pslist_rwlock );
|
||||
|
||||
/* delete from dn2id */
|
||||
rs->sr_err = bdb_dn2id_delete( op, lt2, eip, e );
|
||||
if ( rs->sr_err != 0 ) {
|
||||
|
@ -45,6 +45,9 @@ static void send_paged_response(
|
||||
ID *lastid,
|
||||
int tentries );
|
||||
|
||||
static int bdb_pfid_cmp( const void *v_id1, const void *v_id2 );
|
||||
static ID* bdb_id_dup( Operation *op, ID *id );
|
||||
|
||||
/* Dereference aliases for a single alias entry. Return the final
|
||||
* dereferenced entry on success, NULL on any failure.
|
||||
*/
|
||||
@ -306,6 +309,7 @@ sameido:
|
||||
#define IS_BDB_REPLACE(type) (( type == LDAP_PSEARCH_BY_DELETE ) || \
|
||||
( type == LDAP_PSEARCH_BY_SCOPEOUT ))
|
||||
#define IS_PSEARCH (op != sop)
|
||||
#define IS_POST_SEARCH ( op->ors_post_search_id != NOID )
|
||||
|
||||
static Operation *
|
||||
bdb_drop_psearch( Operation *op, ber_int_t msgid )
|
||||
@ -369,19 +373,170 @@ bdb_cancel( Operation *op, SlapReply *rs )
|
||||
|
||||
int bdb_search( Operation *op, SlapReply *rs )
|
||||
{
|
||||
return bdb_do_search( op, rs, op, NULL, 0 );
|
||||
int rc;
|
||||
struct pc_entry *pce = NULL;
|
||||
struct pc_entry *tmp_pce = NULL;
|
||||
Entry ps_e = {0};
|
||||
Attribute *a;
|
||||
|
||||
ps_e.e_private = NULL;
|
||||
ldap_pvt_thread_mutex_init( &op->o_pcmutex );
|
||||
LDAP_TAILQ_INIT( &op->o_ps_pre_candidates );
|
||||
LDAP_TAILQ_INIT( &op->o_ps_post_candidates );
|
||||
|
||||
op->ors_post_search_id = NOID;
|
||||
rc = bdb_do_search( op, rs, op, NULL, 0 );
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &op->o_pcmutex );
|
||||
pce = LDAP_TAILQ_FIRST( &op->o_ps_post_candidates );
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_pcmutex );
|
||||
|
||||
while ( rc == LDAP_SUCCESS && pce &&
|
||||
op->o_sync_mode & SLAP_SYNC_REFRESH_AND_PERSIST ) {
|
||||
|
||||
ps_e.e_id = op->ors_post_search_id = pce->pc_id;
|
||||
if ( op->o_sync_csn.bv_val ) {
|
||||
ch_free( op->o_sync_csn.bv_val );
|
||||
op->o_sync_csn.bv_val = NULL;
|
||||
}
|
||||
ber_dupbv( &op->o_sync_csn, &pce->pc_csn );
|
||||
ber_dupbv( &ps_e.e_name, &pce->pc_ename );
|
||||
ber_dupbv( &ps_e.e_nname, &pce->pc_enname );
|
||||
a = ch_calloc( 1, sizeof( Attribute ));
|
||||
a->a_desc = slap_schema.si_ad_entryUUID;
|
||||
a->a_vals = ch_calloc( 2, sizeof( struct berval ));
|
||||
ber_dupbv( &a->a_vals[0], &pce->pc_entryUUID );
|
||||
a->a_nvals = a->a_vals;
|
||||
a->a_next = NULL;
|
||||
ps_e.e_attrs = a;
|
||||
|
||||
rc = bdb_do_search( op, rs, op, &ps_e, 0 );
|
||||
|
||||
tmp_pce = pce;
|
||||
ldap_pvt_thread_mutex_lock( &op->o_pcmutex );
|
||||
pce = LDAP_TAILQ_NEXT( pce, pc_link );
|
||||
LDAP_TAILQ_REMOVE( &op->o_ps_post_candidates, tmp_pce, pc_link );
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_pcmutex );
|
||||
|
||||
ch_free( tmp_pce->pc_csn.bv_val );
|
||||
ch_free( tmp_pce->pc_entryUUID.bv_val );
|
||||
ch_free( tmp_pce->pc_ename.bv_val );
|
||||
ch_free( tmp_pce->pc_enname.bv_val );
|
||||
ch_free( tmp_pce );
|
||||
entry_clean( &ps_e );
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int bdb_psearch( Operation *op, SlapReply *rs, Operation *sop,
|
||||
Entry *ps_e, int ps_type )
|
||||
{
|
||||
int rc;
|
||||
struct pc_entry *pce = NULL;
|
||||
struct pc_entry *p = NULL;
|
||||
|
||||
sop->o_private = op->o_private;
|
||||
rc = bdb_do_search( op, rs, sop, ps_e, ps_type );
|
||||
sop->o_private = NULL;
|
||||
op->ors_post_search_id = NOID;
|
||||
|
||||
return rc;
|
||||
switch (ps_type) {
|
||||
case LDAP_PSEARCH_BY_PREMODIFY:
|
||||
case LDAP_PSEARCH_BY_PREDELETE:
|
||||
|
||||
if ( sop->o_refresh_in_progress ) {
|
||||
pce = (struct pc_entry *) ch_calloc( 1, sizeof( struct pc_entry ));
|
||||
pce->pc_id = ps_e->e_id;
|
||||
ldap_pvt_thread_mutex_lock( &sop->o_pcmutex );
|
||||
if ( LDAP_TAILQ_EMPTY( &sop->o_ps_pre_candidates )) {
|
||||
LDAP_TAILQ_INSERT_HEAD( &sop->o_ps_pre_candidates, pce, pc_link );
|
||||
} else {
|
||||
LDAP_TAILQ_FOREACH( p, &sop->o_ps_pre_candidates, pc_link ) {
|
||||
if ( p->pc_id > pce->pc_id )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( p ) {
|
||||
LDAP_TAILQ_INSERT_BEFORE( p, pce, pc_link );
|
||||
} else {
|
||||
LDAP_TAILQ_INSERT_TAIL(
|
||||
&sop->o_ps_pre_candidates,
|
||||
pce, pc_link );
|
||||
}
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &sop->o_pcmutex );
|
||||
} else {
|
||||
rc = bdb_do_search( op, rs, sop, ps_e, ps_type );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Wait until refresh search send the entry */
|
||||
while ( !pce->pc_sent ) {
|
||||
if ( sop->o_refresh_in_progress ) {
|
||||
ldap_pvt_thread_yield();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !sop->o_refresh_in_progress && !pce->pc_sent ) {
|
||||
/* refresh ended without processing pce */
|
||||
/* need to perform psearch for ps_e */
|
||||
ldap_pvt_thread_mutex_lock( &sop->o_pcmutex );
|
||||
LDAP_TAILQ_REMOVE( &sop->o_ps_pre_candidates, pce, pc_link );
|
||||
ldap_pvt_thread_mutex_unlock( &sop->o_pcmutex );
|
||||
ch_free( pce );
|
||||
rc = bdb_do_search( op, rs, sop, ps_e, ps_type );
|
||||
return rc;
|
||||
} else {
|
||||
/* the pce entry was sent in the refresh phase */
|
||||
if ( ps_type == LDAP_PSEARCH_BY_PREMODIFY ) {
|
||||
struct psid_entry* psid_e;
|
||||
psid_e = (struct psid_entry *) ch_calloc(1,
|
||||
sizeof(struct psid_entry));
|
||||
psid_e->ps_op = sop;
|
||||
LDAP_LIST_INSERT_HEAD( &op->o_pm_list, psid_e, ps_link );
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &sop->o_pcmutex );
|
||||
LDAP_TAILQ_REMOVE( &sop->o_ps_pre_candidates, pce, pc_link );
|
||||
ldap_pvt_thread_mutex_unlock( &sop->o_pcmutex );
|
||||
ch_free( pce );
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
break;
|
||||
case LDAP_PSEARCH_BY_DELETE:
|
||||
case LDAP_PSEARCH_BY_SCOPEOUT:
|
||||
case LDAP_PSEARCH_BY_ADD:
|
||||
case LDAP_PSEARCH_BY_MODIFY:
|
||||
ldap_pvt_thread_mutex_lock( &op->o_pcmutex );
|
||||
if ( sop->o_refresh_in_progress ||
|
||||
!LDAP_TAILQ_EMPTY( &sop->o_ps_post_candidates )) {
|
||||
pce = (struct pc_entry *) ch_calloc( 1, sizeof( struct pc_entry ));
|
||||
pce->pc_id = ps_e->e_id;
|
||||
// pce->ps_type = ps_type;
|
||||
ber_dupbv( &pce->pc_csn, &op->o_sync_csn );
|
||||
if ( ps_type == LDAP_PSEARCH_BY_DELETE ) {
|
||||
Attribute *a;
|
||||
for ( a = ps_e->e_attrs; a != NULL; a = a->a_next ) {
|
||||
AttributeDescription *desc = a->a_desc;
|
||||
if ( desc == slap_schema.si_ad_entryUUID ) {
|
||||
ber_dupbv( &pce->pc_entryUUID, &a->a_nvals[0] );
|
||||
}
|
||||
}
|
||||
}
|
||||
ber_dupbv( &pce->pc_ename, &ps_e->e_name );
|
||||
ber_dupbv( &pce->pc_enname, &ps_e->e_nname );
|
||||
LDAP_TAILQ_INSERT_TAIL( &sop->o_ps_post_candidates, pce, pc_link );
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_pcmutex );
|
||||
} else {
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_pcmutex );
|
||||
rc = bdb_do_search( op, rs, sop, ps_e, ps_type );
|
||||
return rc;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Debug( LDAP_DEBUG_TRACE, "do_psearch: invalid psearch type\n",
|
||||
0, 0, 0 );
|
||||
return LDAP_OTHER;
|
||||
}
|
||||
}
|
||||
|
||||
/* For persistent searches, op is the currently executing operation,
|
||||
@ -428,6 +583,7 @@ bdb_do_search( Operation *op, SlapReply *rs, Operation *sop,
|
||||
const char *text;
|
||||
int slog_found = 0;
|
||||
|
||||
struct pc_entry *pce = NULL;
|
||||
BerVarray syncUUID_set = NULL;
|
||||
int syncUUID_set_cnt = 0;
|
||||
|
||||
@ -439,7 +595,8 @@ bdb_do_search( Operation *op, SlapReply *rs, Operation *sop,
|
||||
|
||||
opinfo = (struct bdb_op_info *) op->o_private;
|
||||
|
||||
if ( !IS_PSEARCH && sop->o_sync_mode & SLAP_SYNC_REFRESH_AND_PERSIST ) {
|
||||
if ( !IS_POST_SEARCH && !IS_PSEARCH &&
|
||||
sop->o_sync_mode & SLAP_SYNC_REFRESH_AND_PERSIST ) {
|
||||
struct slap_session_entry *sent;
|
||||
if ( sop->o_sync_state.sid >= 0 ) {
|
||||
LDAP_LIST_FOREACH( sent, &bdb->bi_session_list, se_link ) {
|
||||
@ -452,14 +609,16 @@ bdb_do_search( Operation *op, SlapReply *rs, Operation *sop,
|
||||
}
|
||||
|
||||
/* psearch needs to be registered before refresh begins */
|
||||
/* psearch and refresh transmission is serialized in send_ldap_ber() */
|
||||
if ( !IS_PSEARCH && sop->o_sync_mode & SLAP_SYNC_PERSIST ) {
|
||||
if ( !IS_POST_SEARCH && !IS_PSEARCH &&
|
||||
sop->o_sync_mode & SLAP_SYNC_PERSIST ) {
|
||||
sop->o_refresh_in_progress = 1;
|
||||
ldap_pvt_thread_rdwr_wlock( &bdb->bi_pslist_rwlock );
|
||||
LDAP_LIST_INSERT_HEAD( &bdb->bi_psearch_list, sop, o_ps_link );
|
||||
ldap_pvt_thread_rdwr_wunlock( &bdb->bi_pslist_rwlock );
|
||||
|
||||
} else if ( !IS_PSEARCH && sop->o_sync_mode & SLAP_SYNC_REFRESH_AND_PERSIST
|
||||
&& sop->o_sync_slog_size >= 0 )
|
||||
} else if ( !IS_POST_SEARCH && !IS_PSEARCH &&
|
||||
sop->o_sync_mode & SLAP_SYNC_REFRESH_AND_PERSIST
|
||||
&& sop->o_sync_slog_size >= 0 )
|
||||
{
|
||||
ldap_pvt_thread_rdwr_wlock( &bdb->bi_pslist_rwlock );
|
||||
LDAP_LIST_FOREACH( ps_list, &bdb->bi_psearch_list, o_ps_link ) {
|
||||
@ -545,6 +704,14 @@ bdb_do_search( Operation *op, SlapReply *rs, Operation *sop,
|
||||
}
|
||||
}
|
||||
|
||||
if ( IS_POST_SEARCH ) {
|
||||
cursor = 0;
|
||||
candidates[0] = 1;
|
||||
candidates[1] = op->ors_post_search_id;
|
||||
search_context_csn = ber_dupbv( NULL, &op->o_sync_csn );
|
||||
goto loop_start;
|
||||
}
|
||||
|
||||
if ( sop->o_req_ndn.bv_len == 0 ) {
|
||||
/* DIT root special case */
|
||||
ei_root.bei_e = &e_root;
|
||||
@ -876,13 +1043,64 @@ dn2entry_retry:
|
||||
}
|
||||
}
|
||||
|
||||
loop_start:
|
||||
|
||||
for ( id = bdb_idl_first( candidates, &cursor );
|
||||
id != NOID && !no_sync_state_change;
|
||||
id != NOID && !no_sync_state_change;
|
||||
id = bdb_idl_next( candidates, &cursor ) )
|
||||
{
|
||||
int scopeok = 0;
|
||||
ID* idhole = NULL;
|
||||
|
||||
loop_begin:
|
||||
|
||||
if ( !IS_POST_SEARCH ) {
|
||||
idhole = (ID*) avl_find( sop->o_psearch_finished,
|
||||
(caddr_t)&id, bdb_pfid_cmp );
|
||||
if ( idhole ) {
|
||||
avl_delete( &sop->o_psearch_finished,
|
||||
(caddr_t)idhole, bdb_pfid_cmp );
|
||||
sop->o_tmpfree( idhole, sop->o_tmpmemctx );
|
||||
goto loop_continue;
|
||||
}
|
||||
|
||||
if ( sop->o_refresh_in_progress ) {
|
||||
ldap_pvt_thread_mutex_lock( &sop->o_pcmutex );
|
||||
pce = LDAP_TAILQ_FIRST( &sop->o_ps_pre_candidates );
|
||||
while ( pce && pce->pc_sent ) {
|
||||
pce = LDAP_TAILQ_NEXT( pce, pc_link );
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &sop->o_pcmutex );
|
||||
if ( pce ) {
|
||||
ID pos;
|
||||
if ( BDB_IDL_IS_RANGE( candidates ) ) {
|
||||
if ( pce->pc_id >= candidates[1] &&
|
||||
pce->pc_id <= candidates[2] &&
|
||||
pce->pc_id > cursor-1 ) {
|
||||
id = pce->pc_id;
|
||||
cursor--;
|
||||
avl_insert( &sop->o_psearch_finished,
|
||||
(caddr_t)bdb_id_dup( sop, &pce->pc_id ),
|
||||
bdb_pfid_cmp, avl_dup_error );
|
||||
} else {
|
||||
pce->pc_sent = 1;
|
||||
}
|
||||
} else {
|
||||
pos = bdb_idl_search(candidates, pce->pc_id);
|
||||
if ( pos > cursor-1 && pos <= candidates[0] ) {
|
||||
id = pce->pc_id;
|
||||
cursor--;
|
||||
avl_insert( &sop->o_psearch_finished,
|
||||
(caddr_t)bdb_id_dup( sop, &pce->pc_id ),
|
||||
bdb_pfid_cmp, avl_dup_error );
|
||||
} else {
|
||||
pce->pc_sent = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check for abandon */
|
||||
if ( sop->o_abandon ) {
|
||||
if ( sop != op ) {
|
||||
@ -937,7 +1155,11 @@ id2entry_retry:
|
||||
}
|
||||
|
||||
if ( e == NULL ) {
|
||||
if( !BDB_IDL_IS_RANGE(candidates) ) {
|
||||
if ( IS_POST_SEARCH ) {
|
||||
/* send LDAP_SYNC_DELETE */
|
||||
rs->sr_entry = e = ps_e;
|
||||
goto post_search_no_entry;
|
||||
} else if( !BDB_IDL_IS_RANGE(candidates) ) {
|
||||
/* only complain for non-range IDLs */
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"bdb_search: candidate %ld not found\n",
|
||||
@ -1049,7 +1271,7 @@ id2entry_retry:
|
||||
#endif
|
||||
|
||||
/* Not in scope, ignore it */
|
||||
if ( !scopeok ) {
|
||||
if ( !IS_POST_SEARCH && !scopeok ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"bdb_search: %ld scope not okay\n",
|
||||
(long) id, 0, 0 );
|
||||
@ -1091,29 +1313,39 @@ id2entry_retry:
|
||||
}
|
||||
|
||||
} else {
|
||||
if ( sop->o_sync_mode & SLAP_SYNC_REFRESH ) {
|
||||
rc_sync = test_filter( sop, rs->sr_entry, &cookief );
|
||||
rs->sr_err = test_filter( sop, rs->sr_entry, &contextcsnand );
|
||||
if ( rs->sr_err == LDAP_COMPARE_TRUE ) {
|
||||
if ( rc_sync == LDAP_COMPARE_TRUE ) {
|
||||
if ( no_sync_state_change ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"bdb_search: error in context csn management\n",
|
||||
0, 0, 0 );
|
||||
}
|
||||
entry_sync_state = LDAP_SYNC_ADD;
|
||||
if ( !IS_POST_SEARCH ) {
|
||||
if ( sop->o_sync_mode & SLAP_SYNC_REFRESH ) {
|
||||
rc_sync = test_filter( sop, rs->sr_entry, &cookief );
|
||||
rs->sr_err = test_filter( sop, rs->sr_entry,
|
||||
&contextcsnand );
|
||||
if ( rs->sr_err == LDAP_COMPARE_TRUE ) {
|
||||
if ( rc_sync == LDAP_COMPARE_TRUE ) {
|
||||
if ( no_sync_state_change ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"bdb_search: "
|
||||
"error in context csn management\n",
|
||||
0, 0, 0 );
|
||||
}
|
||||
entry_sync_state = LDAP_SYNC_ADD;
|
||||
|
||||
} else {
|
||||
if ( no_sync_state_change ) {
|
||||
goto loop_continue;
|
||||
} else {
|
||||
if ( no_sync_state_change ) {
|
||||
goto loop_continue;
|
||||
}
|
||||
entry_sync_state = LDAP_SYNC_PRESENT;
|
||||
}
|
||||
entry_sync_state = LDAP_SYNC_PRESENT;
|
||||
}
|
||||
} else {
|
||||
rs->sr_err = test_filter( sop,
|
||||
rs->sr_entry, sop->oq_search.rs_filter );
|
||||
}
|
||||
|
||||
} else {
|
||||
rs->sr_err = test_filter( sop,
|
||||
rs->sr_entry, sop->oq_search.rs_filter );
|
||||
if ( scopeok ) {
|
||||
rs->sr_err = test_filter( sop,
|
||||
rs->sr_entry, sop->oq_search.rs_filter );
|
||||
} else {
|
||||
rs->sr_err = LDAP_COMPARE_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1147,16 +1379,17 @@ id2entry_retry:
|
||||
/* safe default */
|
||||
int result = -1;
|
||||
|
||||
if (IS_PSEARCH) {
|
||||
if (IS_PSEARCH || IS_POST_SEARCH) {
|
||||
int premodify_found = 0;
|
||||
int entry_sync_state;
|
||||
|
||||
if ( ps_type == LDAP_PSEARCH_BY_ADD ||
|
||||
if ( IS_POST_SEARCH ||
|
||||
ps_type == LDAP_PSEARCH_BY_ADD ||
|
||||
ps_type == LDAP_PSEARCH_BY_DELETE ||
|
||||
ps_type == LDAP_PSEARCH_BY_MODIFY ||
|
||||
ps_type == LDAP_PSEARCH_BY_SCOPEOUT )
|
||||
{
|
||||
if ( ps_type == LDAP_PSEARCH_BY_MODIFY ) {
|
||||
if ( !IS_POST_SEARCH &&
|
||||
ps_type == LDAP_PSEARCH_BY_MODIFY ) {
|
||||
struct psid_entry* psid_e;
|
||||
LDAP_LIST_FOREACH( psid_e,
|
||||
&op->o_pm_list, ps_link)
|
||||
@ -1170,7 +1403,14 @@ id2entry_retry:
|
||||
if (psid_e != NULL) free (psid_e);
|
||||
}
|
||||
|
||||
if ( ps_type == LDAP_PSEARCH_BY_ADD ) {
|
||||
if ( IS_POST_SEARCH ) {
|
||||
if ( scopeok ) {
|
||||
entry_sync_state = LDAP_SYNC_ADD;
|
||||
} else {
|
||||
post_search_no_entry:
|
||||
entry_sync_state = LDAP_SYNC_DELETE;
|
||||
}
|
||||
} else if ( ps_type == LDAP_PSEARCH_BY_ADD ) {
|
||||
entry_sync_state = LDAP_SYNC_ADD;
|
||||
} else if ( ps_type == LDAP_PSEARCH_BY_DELETE ) {
|
||||
entry_sync_state = LDAP_SYNC_DELETE;
|
||||
@ -1199,11 +1439,16 @@ id2entry_retry:
|
||||
search_context_csn,
|
||||
sop->o_sync_state.sid,
|
||||
sop->o_sync_state.rid );
|
||||
rs->sr_err = slap_build_sync_state_ctrl( sop,
|
||||
rs, e, entry_sync_state, ctrls,
|
||||
rs->sr_err = slap_build_sync_state_ctrl(
|
||||
sop, rs, e, entry_sync_state, ctrls,
|
||||
num_ctrls++, 1, &cookie );
|
||||
if ( rs->sr_err != LDAP_SUCCESS ) goto done;
|
||||
rs->sr_attrs = attrs;
|
||||
if (!(IS_POST_SEARCH &&
|
||||
entry_sync_state == LDAP_SYNC_DELETE)) {
|
||||
rs->sr_attrs = attrs;
|
||||
} else {
|
||||
rs->sr_attrs = NULL;
|
||||
}
|
||||
rs->sr_operational_attrs = NULL;
|
||||
rs->sr_ctrls = ctrls;
|
||||
rs->sr_flags = 0;
|
||||
@ -1235,8 +1480,8 @@ id2entry_retry:
|
||||
} else {
|
||||
if ( sop->o_sync_mode & SLAP_SYNC_REFRESH ) {
|
||||
if ( rc_sync == LDAP_COMPARE_TRUE ) { /* ADD */
|
||||
rs->sr_err = slap_build_sync_state_ctrl( sop,
|
||||
rs, e, entry_sync_state, ctrls,
|
||||
rs->sr_err = slap_build_sync_state_ctrl(
|
||||
sop, rs, e, entry_sync_state, ctrls,
|
||||
num_ctrls++, 0, NULL );
|
||||
if ( rs->sr_err != LDAP_SUCCESS ) goto done;
|
||||
rs->sr_ctrls = ctrls;
|
||||
@ -1321,15 +1566,24 @@ loop_continue:
|
||||
if( e != NULL ) {
|
||||
/* free reader lock */
|
||||
if (!IS_PSEARCH) {
|
||||
bdb_cache_return_entry_r( bdb->bi_dbenv,
|
||||
&bdb->bi_cache, e , &lock );
|
||||
if ( sop->o_nocaching ) {
|
||||
bdb_cache_delete_entry( bdb, ei, locker, &lock );
|
||||
if (!(IS_POST_SEARCH &&
|
||||
entry_sync_state == LDAP_SYNC_DELETE)) {
|
||||
bdb_cache_return_entry_r( bdb->bi_dbenv,
|
||||
&bdb->bi_cache, e , &lock );
|
||||
if ( sop->o_nocaching ) {
|
||||
bdb_cache_delete_entry( bdb, ei, locker, &lock );
|
||||
}
|
||||
}
|
||||
}
|
||||
e = NULL;
|
||||
rs->sr_entry = NULL;
|
||||
}
|
||||
|
||||
if ( sop->o_refresh_in_progress ) {
|
||||
if ( pce ) {
|
||||
pce->pc_sent = 1;
|
||||
}
|
||||
}
|
||||
|
||||
ldap_pvt_thread_yield();
|
||||
}
|
||||
@ -1345,7 +1599,7 @@ loop_continue:
|
||||
}
|
||||
|
||||
nochange:
|
||||
if (!IS_PSEARCH) {
|
||||
if (!IS_PSEARCH && !IS_POST_SEARCH) {
|
||||
if ( sop->o_sync_mode & SLAP_SYNC_REFRESH ) {
|
||||
if ( sop->o_sync_mode & SLAP_SYNC_PERSIST ) {
|
||||
struct berval cookie;
|
||||
@ -1458,9 +1712,17 @@ nochange:
|
||||
}
|
||||
}
|
||||
|
||||
if ( sop->o_refresh_in_progress ) {
|
||||
sop->o_refresh_in_progress = 0;
|
||||
}
|
||||
|
||||
rs->sr_err = LDAP_SUCCESS;
|
||||
|
||||
done:
|
||||
if ( sop->o_psearch_finished ) {
|
||||
avl_free( sop->o_psearch_finished, ch_free );
|
||||
}
|
||||
|
||||
if( !IS_PSEARCH && e != NULL ) {
|
||||
/* free reader lock */
|
||||
bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
|
||||
@ -1849,3 +2111,18 @@ done:
|
||||
(void) ber_free_buf( ber );
|
||||
}
|
||||
|
||||
static int
|
||||
bdb_pfid_cmp( const void *v_id1, const void *v_id2 )
|
||||
{
|
||||
const ID *p1 = v_id1, *p2 = v_id2;
|
||||
return *p1 - *p2;
|
||||
}
|
||||
|
||||
static ID*
|
||||
bdb_id_dup( Operation *op, ID *id )
|
||||
{
|
||||
ID *new;
|
||||
new = ch_malloc( sizeof(ID) );
|
||||
*new = *id;
|
||||
return new;
|
||||
}
|
||||
|
@ -694,8 +694,8 @@ LDAP_SLAPD_V (int) krbv4_ldap_auth();
|
||||
* ldapsync.c
|
||||
*/
|
||||
LDAP_SLAPD_F (int) slap_build_sync_state_ctrl LDAP_P((
|
||||
Operation *, SlapReply *, Entry *, int, LDAPControl **,
|
||||
int, int, struct berval * ));
|
||||
Operation *, SlapReply *, Entry *, int,
|
||||
LDAPControl **, int, int, struct berval * ));
|
||||
LDAP_SLAPD_F (int) slap_build_sync_done_ctrl LDAP_P((
|
||||
Operation *, SlapReply *, LDAPControl **,
|
||||
int, int, struct berval *, int ));
|
||||
|
@ -1662,6 +1662,7 @@ typedef struct req_search_s {
|
||||
AttributeName *rs_attrs;
|
||||
Filter *rs_filter;
|
||||
struct berval rs_filterstr;
|
||||
int rs_post_search_id;
|
||||
} req_search_s;
|
||||
|
||||
typedef struct req_compare_s {
|
||||
@ -1998,6 +1999,7 @@ typedef struct slap_paged_state {
|
||||
#define LDAP_PSEARCH_BY_PREMODIFY 0x03
|
||||
#define LDAP_PSEARCH_BY_MODIFY 0x04
|
||||
#define LDAP_PSEARCH_BY_SCOPEOUT 0x05
|
||||
#define LDAP_PSEARCH_BY_PREDELETE 0x06
|
||||
|
||||
struct psid_entry {
|
||||
struct slap_op *ps_op;
|
||||
@ -2029,6 +2031,16 @@ struct slap_csn_entry {
|
||||
LDAP_TAILQ_ENTRY (slap_csn_entry) ce_csn_link;
|
||||
};
|
||||
|
||||
struct pc_entry {
|
||||
ID pc_id;
|
||||
int pc_sent;
|
||||
struct berval pc_csn;
|
||||
struct berval pc_entryUUID;
|
||||
struct berval pc_ename;
|
||||
struct berval pc_enname;
|
||||
LDAP_TAILQ_ENTRY( pc_entry ) pc_link;
|
||||
};
|
||||
|
||||
/*
|
||||
* Caches the result of a backend_group check for ACL evaluation
|
||||
*/
|
||||
@ -2101,6 +2113,7 @@ typedef struct slap_op {
|
||||
#define ors_attrs oq_search.rs_attrs
|
||||
#define ors_filter oq_search.rs_filter
|
||||
#define ors_filterstr oq_search.rs_filterstr
|
||||
#define ors_post_search_id oq_search.rs_post_search_id
|
||||
|
||||
#define orr_newrdn oq_modrdn.rs_newrdn
|
||||
#define orr_nnewrdn oq_modrdn.rs_nnewrdn
|
||||
@ -2202,6 +2215,12 @@ typedef struct slap_op {
|
||||
LDAP_LIST_ENTRY(slap_op) o_ps_link;
|
||||
LDAP_LIST_HEAD(pe, psid_entry) o_pm_list;
|
||||
|
||||
int o_refresh_in_progress;
|
||||
LDAP_TAILQ_HEAD(pc_pre, pc_entry) o_ps_pre_candidates;
|
||||
LDAP_TAILQ_HEAD(pc_post, pc_entry) o_ps_post_candidates;
|
||||
Avlnode *o_psearch_finished;
|
||||
ldap_pvt_thread_mutex_t o_pcmutex;
|
||||
|
||||
AuthorizationInformation o_authz;
|
||||
|
||||
BerElement *o_ber; /* ber of the request */
|
||||
|
@ -48,6 +48,9 @@ static int dn_callback( struct slap_op *, struct slap_rep * );
|
||||
static int nonpresent_callback( struct slap_op *, struct slap_rep * );
|
||||
static int null_callback( struct slap_op *, struct slap_rep * );
|
||||
|
||||
static int si_refreshDelete = 0;
|
||||
static int si_refreshPresent = 0;
|
||||
|
||||
static AttributeDescription *sync_descs[4];
|
||||
|
||||
struct runqueue_s syncrepl_rq;
|
||||
@ -588,7 +591,7 @@ do_syncrep2(
|
||||
ldap_get_entry_controls( si->si_ld, msg, &rctrls );
|
||||
/* we can't work without the control */
|
||||
if ( !rctrls ) {
|
||||
Debug( LDAP_DEBUG_ANY, "do_syncrep2 : "
|
||||
Debug( LDAP_DEBUG_ANY, "do_syncrep2: "
|
||||
"got search entry without "
|
||||
"control\n", 0, 0, 0 );
|
||||
rc = -1;
|
||||
@ -632,10 +635,12 @@ do_syncrep2(
|
||||
|
||||
case LDAP_RES_SEARCH_REFERENCE:
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"do_syncrep2 : reference received\n", 0, 0, 0 );
|
||||
"do_syncrep2: reference received error\n", 0, 0, 0 );
|
||||
break;
|
||||
|
||||
case LDAP_RES_SEARCH_RESULT:
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"do_syncrep2: LDAP_RES_SEARCH_RESULT\n", 0, 0, 0 );
|
||||
ldap_parse_result( si->si_ld, msg, &err, NULL, NULL, NULL,
|
||||
&rctrls, 0 );
|
||||
if ( rctrls ) {
|
||||
@ -703,18 +708,31 @@ do_syncrep2(
|
||||
rc = ldap_parse_intermediate( si->si_ld, msg,
|
||||
&retoid, &retdata, NULL, 0 );
|
||||
if ( !rc && !strcmp( retoid, LDAP_SYNC_INFO ) ) {
|
||||
int si_refreshDelete = 0;
|
||||
int si_refreshPresent = 0;
|
||||
ber_init2( ber, retdata, LBER_USE_DER );
|
||||
|
||||
switch ( si_tag = ber_peek_tag( ber, &len )) {
|
||||
ber_tag_t tag;
|
||||
case LDAP_TAG_SYNC_NEW_COOKIE:
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"do_syncrep2: %s - %s%s\n",
|
||||
"LDAP_RES_INTERMEDIATE",
|
||||
"NEW_COOKIE", "\n" );
|
||||
ber_scanf( ber, "tm", &tag, &cookie );
|
||||
break;
|
||||
case LDAP_TAG_SYNC_REFRESH_DELETE:
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"do_syncrep2: %s - %s%s\n",
|
||||
"LDAP_RES_INTERMEDIATE",
|
||||
"REFRESH_DELETE\n", "\n" );
|
||||
si_refreshDelete = 1;
|
||||
case LDAP_TAG_SYNC_REFRESH_PRESENT:
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"do_syncrep2: %s - %s%s\n",
|
||||
"LDAP_RES_INTERMEDIATE",
|
||||
si_tag == LDAP_TAG_SYNC_REFRESH_PRESENT ?
|
||||
"REFRESH_PRESENT" : "REFRESH_DELETE",
|
||||
"\n" );
|
||||
si_refreshDelete = 1;
|
||||
si_refreshPresent = 1;
|
||||
ber_scanf( ber, "t{" /*"}"*/, &tag );
|
||||
if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE )
|
||||
@ -740,6 +758,11 @@ do_syncrep2(
|
||||
ber_scanf( ber, /*"{"*/ "}" );
|
||||
break;
|
||||
case LDAP_TAG_SYNC_ID_SET:
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"do_syncrep2: %s - %s%s\n",
|
||||
"LDAP_RES_INTERMEDIATE",
|
||||
"SYNC_ID_SET",
|
||||
"\n" );
|
||||
ber_scanf( ber, "t{" /*"}"*/, &tag );
|
||||
if ( ber_peek_tag( ber, &len ) ==
|
||||
LDAP_TAG_SYNC_COOKIE )
|
||||
@ -775,8 +798,8 @@ do_syncrep2(
|
||||
slap_sl_free( syncUUIDs, op->o_tmpmemctx );
|
||||
break;
|
||||
default:
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"do_syncrep2 : unknown syncinfo tag (%ld)\n",
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"do_syncrep2 : unknown syncinfo tag (%ld)\n",
|
||||
(long) si_tag, 0, 0 );
|
||||
ldap_memfree( retoid );
|
||||
ber_bvfree( retdata );
|
||||
@ -919,6 +942,8 @@ do_syncrepl(
|
||||
/* Establish session, do search */
|
||||
if ( !si->si_ld ) {
|
||||
first = 1;
|
||||
si_refreshDelete = 0;
|
||||
si_refreshPresent = 0;
|
||||
rc = do_syncrep1( &op, si );
|
||||
}
|
||||
|
||||
@ -1170,10 +1195,42 @@ syncrepl_entry(
|
||||
struct berval org_ndn = BER_BVNULL;
|
||||
int org_managedsait;
|
||||
|
||||
Debug( LDAP_DEBUG_SYNC, "%s: %s",
|
||||
"syncrepl_entry",
|
||||
"LDAP_RES_SEARCH_ENTRY", 0 );
|
||||
switch( syncstate ) {
|
||||
case LDAP_SYNC_PRESENT:
|
||||
Debug( LDAP_DEBUG_SYNC, "%s: %s",
|
||||
"syncrepl_entry",
|
||||
"LDAP_SYNC_PRESENT", "\n" );
|
||||
break;
|
||||
case LDAP_SYNC_ADD:
|
||||
Debug( LDAP_DEBUG_SYNC, "%s: %s",
|
||||
"syncrepl_entry",
|
||||
"LDAP_SYNC_ADD", "\n" );
|
||||
break;
|
||||
case LDAP_SYNC_DELETE:
|
||||
Debug( LDAP_DEBUG_SYNC, "%s: %s",
|
||||
"syncrepl_entry",
|
||||
"LDAP_SYNC_DELETE", "\n" );
|
||||
break;
|
||||
case LDAP_SYNC_MODIFY:
|
||||
Debug( LDAP_DEBUG_SYNC, "%s: %s",
|
||||
"syncrepl_entry",
|
||||
"LDAP_SYNC_MODIFY", "\n" );
|
||||
break;
|
||||
default:
|
||||
Debug( LDAP_DEBUG_ANY, "%s: %s",
|
||||
"syncrepl_entry",
|
||||
"UNKNONW syncstate", "\n" );
|
||||
}
|
||||
|
||||
if (( syncstate == LDAP_SYNC_PRESENT || syncstate == LDAP_SYNC_ADD )) {
|
||||
syncuuid_bv = ber_dupbv( NULL, syncUUID );
|
||||
avl_insert( &si->si_presentlist, (caddr_t) syncuuid_bv,
|
||||
syncuuid_cmp, avl_dup_error );
|
||||
if ( !si_refreshPresent ) {
|
||||
syncuuid_bv = ber_dupbv( NULL, syncUUID );
|
||||
avl_insert( &si->si_presentlist, (caddr_t) syncuuid_bv,
|
||||
syncuuid_cmp, avl_dup_error );
|
||||
}
|
||||
}
|
||||
|
||||
if ( syncstate == LDAP_SYNC_PRESENT ) {
|
||||
@ -1222,6 +1279,9 @@ syncrepl_entry(
|
||||
|
||||
if ( limits_check( op, &rs_search ) == 0 ) {
|
||||
rc = be->be_search( op, &rs_search );
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"syncrepl_entry: %s (%d)\n",
|
||||
"be_search", rc, 0 );
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &op->ors_filterstr ) ) {
|
||||
@ -1231,7 +1291,18 @@ syncrepl_entry(
|
||||
cb.sc_response = null_callback;
|
||||
cb.sc_private = si;
|
||||
|
||||
if ( rs_search.sr_err == LDAP_SUCCESS && !BER_BVISNULL( &si->si_syncUUID_ndn ) )
|
||||
if ( entry && entry->e_name.bv_val ) {
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"syncrepl_entry: %s\n",
|
||||
entry->e_name.bv_val, 0, 0 );
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"syncrepl_entry: %s\n",
|
||||
si->si_syncUUID_ndn.bv_val, 0, 0 );
|
||||
}
|
||||
|
||||
if ( rs_search.sr_err == LDAP_SUCCESS &&
|
||||
!BER_BVISNULL( &si->si_syncUUID_ndn ))
|
||||
{
|
||||
char *subseq_ptr;
|
||||
|
||||
@ -1250,6 +1321,9 @@ syncrepl_entry(
|
||||
op->o_req_ndn = si->si_syncUUID_ndn;
|
||||
op->o_tag = LDAP_REQ_DELETE;
|
||||
rc = be->be_delete( op, &rs_delete );
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"syncrepl_entry: %s (%d)\n",
|
||||
"be_delete", rc, 0 );
|
||||
|
||||
org_req_dn = op->o_req_dn;
|
||||
org_req_ndn = op->o_req_ndn;
|
||||
@ -1303,6 +1377,9 @@ syncrepl_entry(
|
||||
op->o_req_ndn = entry->e_nname;
|
||||
|
||||
rc = be->be_add( op, &rs_add );
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"syncrepl_entry: %s (%d)\n",
|
||||
"be_add", rc, 0 );
|
||||
|
||||
if ( rs_add.sr_err != LDAP_SUCCESS ) {
|
||||
if ( rs_add.sr_err == LDAP_ALREADY_EXISTS &&
|
||||
@ -1330,6 +1407,9 @@ syncrepl_entry(
|
||||
op->o_req_ndn = entry->e_nname;
|
||||
|
||||
rc = be->be_modify( op, &rs_modify );
|
||||
Debug( LDAP_DEBUG_SYNC,
|
||||
"syncrepl_entry: %s (%d)\n",
|
||||
"be_modify", rc, 0 );
|
||||
if ( rs_modify.sr_err != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"syncrepl_entry : be_modify failed (%d)\n",
|
||||
|
Loading…
x
Reference in New Issue
Block a user