]> git.sur5r.net Git - openldap/commitdiff
syncrepl consistency patch
authorJong Hyuk Choi <jongchoi@openldap.org>
Sat, 9 Oct 2004 09:26:16 +0000 (09:26 +0000)
committerJong Hyuk Choi <jongchoi@openldap.org>
Sat, 9 Oct 2004 09:26:16 +0000 (09:26 +0000)
include/ldap_log.h
servers/slapd/back-bdb/delete.c
servers/slapd/back-bdb/search.c
servers/slapd/proto-slap.h
servers/slapd/slap.h
servers/slapd/syncrepl.c

index d053bdf78dee143426145b5203ab35b3438fda88..299e25f24af10cf574fc98112dc84b5bbb3e713d 100644 (file)
@@ -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
index 80dfedaa74eb4fb0c90dd102d2ef342ba665d1df..be55bf1a947265dcb4bebb26d1b080ba2130e61e 100644 (file)
@@ -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 ) {
index 39f84b4e0c490020c47d32d3ad65d983a710f45f..be4c526df677d8f642c14f8c3cc58e65145bb79d 100644 (file)
@@ -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;
+}
index 244d4ccd86bd63ed70a61a4210558cd8bddd21d4..c1b316d8fcf7764f8d3cbb7553bfa22d199c7dde 100644 (file)
@@ -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 ));
index 6b762c6bbcc7b3697a40a59a7ce3ead68a00dad9..5d7b4f91e8806d1e4baf0cf66bc980c324fe590c 100644 (file)
@@ -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 */
index 2389fcb1b5374f9ea4455cab98c84208a7ec14d8..a043f13f8f5ed52d269b3f0c0ee799bcfab663e7 100644 (file)
@@ -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",