]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/syncrepl.c
back-mdb Multival fixes
[openldap] / servers / slapd / syncrepl.c
index 6e157e700c63926a8dd3083c4f79673934ea0cfe..36d01d85bf7d69d759ed39abef7ac73497ae4324 100644 (file)
@@ -46,11 +46,13 @@ struct nonpresent_entry {
 
 typedef struct cookie_state {
        ldap_pvt_thread_mutex_t cs_mutex;
+       ldap_pvt_thread_cond_t cs_cond;
        struct berval *cs_vals;
        int *cs_sids;
        int     cs_num;
        int cs_age;
        int cs_ref;
+       int cs_updating;
 
        /* pending changes, not yet committed */
        ldap_pvt_thread_mutex_t cs_pmutex;
@@ -150,7 +152,7 @@ static int syncrepl_entry(
                                        struct berval *cookieCSN );
 static int syncrepl_updateCookie(
                                        syncinfo_t *, Operation *,
-                                       struct sync_cookie * );
+                                       struct sync_cookie *, int save );
 static struct berval * slap_uuidstr_from_normalized(
                                        struct berval *, struct berval *, void * );
 static int syncrepl_add_glue_ancestors(
@@ -1027,7 +1029,7 @@ do_syncrep2(
                                if ( ( rc = syncrepl_message_to_op( si, op, msg ) ) == LDAP_SUCCESS &&
                                        syncCookie.ctxcsn )
                                {
-                                       rc = syncrepl_updateCookie( si, op, &syncCookie );
+                                       rc = syncrepl_updateCookie( si, op, &syncCookie, 0 );
                                } else switch ( rc ) {
                                        case LDAP_ALREADY_EXISTS:
                                        case LDAP_NO_SUCH_OBJECT:
@@ -1055,7 +1057,7 @@ do_syncrep2(
                                        syncstate, syncUUID, syncCookie.ctxcsn ) ) == LDAP_SUCCESS &&
                                        syncCookie.ctxcsn )
                                {
-                                       rc = syncrepl_updateCookie( si, op, &syncCookie );
+                                       rc = syncrepl_updateCookie( si, op, &syncCookie, 0 );
                                }
                        }
                        if ( punlock >= 0 ) {
@@ -1201,7 +1203,7 @@ do_syncrep2(
                        }
                        if ( syncCookie.ctxcsn && match < 0 && err == LDAP_SUCCESS )
                        {
-                               rc = syncrepl_updateCookie( si, op, &syncCookie );
+                               rc = syncrepl_updateCookie( si, op, &syncCookie, 1 );
                        }
                        if ( si->si_refreshCount ) {
                                LDAP_SLIST_REMOVE( &op->o_extra, si->si_refreshTxn, OpExtra, oe_next );
@@ -1391,7 +1393,7 @@ do_syncrep2(
 
                                        if ( syncCookie.ctxcsn )
                                        {
-                                               rc = syncrepl_updateCookie( si, op, &syncCookie);
+                                               rc = syncrepl_updateCookie( si, op, &syncCookie, 1 );
                                        }
                                        if ( si->si_presentlist ) {
                                                presentlist_free( si->si_presentlist );
@@ -2447,6 +2449,9 @@ syncrepl_message_to_op(
        op->o_callback = &cb;
        slap_op_time( &op->o_time, &op->o_tincr );
 
+       Debug( LDAP_DEBUG_SYNC, "syncrepl_message_to_op: %s tid %x\n",
+               si->si_ridtxt, op->o_tid, 0 );
+
        switch( op->o_tag ) {
        case LDAP_REQ_ADD:
        case LDAP_REQ_MODIFY:
@@ -2954,8 +2959,8 @@ syncrepl_entry(
        int     freecsn = 1;
 
        Debug( LDAP_DEBUG_SYNC,
-               "syncrepl_entry: %s LDAP_RES_SEARCH_ENTRY(LDAP_SYNC_%s)\n",
-               si->si_ridtxt, syncrepl_state2str( syncstate ), 0 );
+               "syncrepl_entry: %s LDAP_RES_SEARCH_ENTRY(LDAP_SYNC_%s) tid %x\n",
+               si->si_ridtxt, syncrepl_state2str( syncstate ), op->o_tid );
 
        if (( syncstate == LDAP_SYNC_PRESENT || syncstate == LDAP_SYNC_ADD ) ) {
                if ( !si->si_refreshPresent && !si->si_refreshDone ) {
@@ -3926,7 +3931,8 @@ static int
 syncrepl_updateCookie(
        syncinfo_t *si,
        Operation *op,
-       struct sync_cookie *syncCookie )
+       struct sync_cookie *syncCookie,
+       int save )
 {
        Backend *be = op->o_bd;
        Modifications mod;
@@ -3950,6 +3956,8 @@ syncrepl_updateCookie(
        mod.sml_next = NULL;
 
        ldap_pvt_thread_mutex_lock( &si->si_cookieState->cs_mutex );
+       while ( si->si_cookieState->cs_updating )
+               ldap_pvt_thread_cond_wait( &si->si_cookieState->cs_cond, &si->si_cookieState->cs_mutex );
 
 #ifdef CHECK_CSN
        for ( i=0; i<syncCookie->numcsns; i++ ) {
@@ -4012,6 +4020,10 @@ syncrepl_updateCookie(
                ch_free( sc.sids );
                return 0;
        }
+
+       si->si_cookieState->cs_updating = 1;
+       ldap_pvt_thread_mutex_unlock( &si->si_cookieState->cs_mutex );
+
        op->o_bd = si->si_wbe;
        slap_queue_csn( op, &first );
 
@@ -4025,7 +4037,11 @@ syncrepl_updateCookie(
        op->o_req_ndn = si->si_contextdn;
 
        /* update contextCSN */
-       op->o_dont_replicate = 1;
+       op->o_dont_replicate = !save;
+
+       /* avoid timestamp collisions */
+       if ( save )
+               slap_op_time( &op->o_time, &op->o_tincr );
 
        mod.sml_numvals = sc.numcsns;
        mod.sml_values = sc.ctxcsn;
@@ -4042,6 +4058,8 @@ syncrepl_updateCookie(
                Entry *e = slap_create_context_csn_entry( op->o_bd, NULL );
                rs_reinit( &rs_modify, REP_RESULT );
                rc = slap_mods2entry( &mod, &e, 0, 1, &text, txtbuf, textlen);
+               slap_queue_csn( op, &first );
+               op->o_tag = LDAP_REQ_ADD;
                op->ora_e = e;
                rc = op->o_bd->be_add( op, &rs_modify );
                if ( e == op->ora_e )
@@ -4050,6 +4068,7 @@ syncrepl_updateCookie(
 
        op->orm_no_opattrs = 0;
        op->o_dont_replicate = 0;
+       ldap_pvt_thread_mutex_lock( &si->si_cookieState->cs_mutex );
 
        if ( rs_modify.sr_err == LDAP_SUCCESS ) {
                slap_sync_cookie_free( &si->si_syncCookie, 0 );
@@ -4082,6 +4101,8 @@ syncrepl_updateCookie(
        }
 #endif
 
+       si->si_cookieState->cs_updating = 0;
+       ldap_pvt_thread_cond_broadcast( &si->si_cookieState->cs_cond );
        ldap_pvt_thread_mutex_unlock( &si->si_cookieState->cs_mutex );
 
        op->o_bd = be;
@@ -4746,6 +4767,7 @@ syncinfo_free( syncinfo_t *sie, int free_all )
                        if ( !sie->si_cookieState->cs_ref ) {
                                ch_free( sie->si_cookieState->cs_sids );
                                ber_bvarray_free( sie->si_cookieState->cs_vals );
+                               ldap_pvt_thread_cond_destroy( &sie->si_cookieState->cs_cond );
                                ldap_pvt_thread_mutex_destroy( &sie->si_cookieState->cs_mutex );
                                ch_free( sie->si_cookieState->cs_psids );
                                ber_bvarray_free( sie->si_cookieState->cs_pvals );
@@ -5552,6 +5574,7 @@ add_syncrepl(
                        si->si_cookieState = ch_calloc( 1, sizeof( cookie_state ));
                        ldap_pvt_thread_mutex_init( &si->si_cookieState->cs_mutex );
                        ldap_pvt_thread_mutex_init( &si->si_cookieState->cs_pmutex );
+                       ldap_pvt_thread_cond_init( &si->si_cookieState->cs_cond );
 
                        c->be->be_syncinfo = si;
                }