]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/syncrepl.c
ITS#2607: improve socket() error logging with AF info
[openldap] / servers / slapd / syncrepl.c
index 261287c5eb4abebc3628bbc597c4e74825f531c5..6ddc6d1c58ac616af90a4e91b77a7e49b18a0c74 100644 (file)
 
 #include "ldap_rq.h"
 
-static Entry*
-syncrepl_message_to_entry ( LDAP *, Operation *, LDAPMessage *,
-               Modifications **, int*, struct berval *, struct berval * );
-
-static int
-syncrepl_entry( LDAP *, Operation*, Entry*, Modifications*,
-               int, struct berval*, struct berval*, int );
-
-static int
-syncrepl_del_nonpresent( LDAP *, Operation * );
-
 static void
-syncrepl_add_glue( LDAP *, Operation*, Entry*, Modifications*, int,
-                  struct berval*, struct berval* );
+syncrepl_del_nonpresent( syncinfo_t *, LDAP *, Operation * );
 
 static void
-syncrepl_updateCookie( LDAP *, Operation *, struct berval *, struct berval * );
+syncrepl_add_glue( syncinfo_t *, LDAP *, Operation*, Entry*, Modifications*,
+                                  int, struct berval*, struct berval* );
 
 static int
-slap_mods_check_syncrepl( Operation *, Modifications **,
+slap_mods_check_syncrepl( syncinfo_t *, Operation *, Modifications **,
                          const char **, char *, size_t, void *ctx );
 
 static int
-slap_mods_opattrs_syncrepl( Operation *, Modifications *, Modifications **,
-                               const char **, char *, size_t );
+slap_mods_opattrs_syncrepl( syncinfo_t *, Operation *, Modifications *,
+                                                       Modifications **, const char **, char *, size_t );
 
 static int
-slap_mods2entry_syncrepl( Modifications *, Entry **, int,
-                         const char **, char *, size_t );
+slap_mods2entry_syncrepl( syncinfo_t *, Modifications *, Entry **, int,
+                                                 const char **, char *, size_t );
 
 /* callback functions */
 static int cookie_callback( struct slap_op *, struct slap_rep * );
+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 * );
 
@@ -113,14 +103,83 @@ init_syncrepl()
        del_descs_lastmod[3] = NULL;
 }
 
+int
+ldap_sync_search(
+       syncinfo_t *si,
+       LDAP *ld,
+       LDAPControl **sctrls,
+       LDAPControl **cctrls,
+       int *msgidp )
+{
+       BerElement      *ber;
+       int timelimit;
+       ber_int_t id;
+
+       int rc;
+       BerElement      *sync_ber = NULL;
+       struct berval *sync_bvalp = NULL;
+       LDAPControl c[2];
+       LDAPControl **ctrls;
+       int err;
+
+    /* setup LDAP SYNC control */
+    sync_ber = ber_alloc_t( LBER_USE_DER );
+    ber_set_option( sync_ber, LBER_OPT_BER_MEMCTX, NULL );
+
+    if ( si->syncCookie ) {
+        ber_printf( sync_ber, "{eO}", abs(si->type), si->syncCookie );
+    } else {
+        ber_printf( sync_ber, "{e}", abs(si->type) );
+    }
+
+    if ( ber_flatten( sync_ber, &sync_bvalp ) == LBER_ERROR ) {
+        ber_free( sync_ber, 1 );
+        return LBER_ERROR;
+    }
+    ber_free( sync_ber, 1 );
+
+    ctrls = (LDAPControl**) sl_calloc( 3, sizeof(LDAPControl*), NULL );
+
+    c[0].ldctl_oid = LDAP_CONTROL_SYNC;
+    c[0].ldctl_value = (*sync_bvalp);
+    c[0].ldctl_iscritical = si->type < 0;
+    ctrls[0] = &c[0];
+
+    if ( si->authzId ) {
+        c[1].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
+        c[1].ldctl_value.bv_val = si->authzId;
+        c[1].ldctl_value.bv_len = strlen( si->authzId );
+        c[1].ldctl_iscritical = 1;
+        ctrls[1] = &c[1];
+    } else {
+        ctrls[1] = NULL;
+    }
+
+    ctrls[2] = NULL;
+
+    err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
+
+    ber_bvfree( sync_bvalp );
+    ch_free( ctrls );
+
+    if ( err != LDAP_OPT_SUCCESS )
+        fprintf( stderr, "Could not set controls : %d\n", err );
+
+       rc = ldap_search_ext( ld, si->base, si->scope, si->filterstr,
+                                                 si->attrs, si->attrsonly, sctrls, cctrls,
+                                                 si->tlimit, si->slimit, msgidp );
+
+       return rc;
+}
+
 void *
 do_syncrepl(
        void    *ctx,
        void    *arg )
 {
        struct re_s* rtask = arg;
-       Backend *be = rtask->private;
-       syncinfo_t *si = ( syncinfo_t * ) be->syncinfo;
+       syncinfo_t *si = ( syncinfo_t * ) rtask->arg;
+       Backend *be = si->be;
 
        SlapReply       rs = {REP_RESULT};
 
@@ -202,32 +261,17 @@ do_syncrepl(
 
        /* Init connection to master */
 
-       if ( ldap_is_ldap_url( si->masteruri )) {
-               rc = ldap_initialize( &ld, si->masteruri );
-               if ( rc != LDAP_SUCCESS ) {
-#ifdef NEW_LOGGING
-                       LDAP_LOG( OPERATION, ERR, "do_syncrepl: "
-                               "ldap_initialize failed (%s)\n",
-                               si->masteruri, 0, 0 );
-#else
-                       Debug( LDAP_DEBUG_ANY, "do_syncrepl: "
-                               "ldap_initialize failed (%s)\n",
-                               si->masteruri, 0, 0 );
-#endif
-               }
-       } else {
-               ld = ldap_init( si->mastername, si->masterport );
-               if ( ld == NULL ) {
+       rc = ldap_initialize( &ld, si->masteruri );
+       if ( rc != LDAP_SUCCESS ) {
 #ifdef NEW_LOGGING
-                       LDAP_LOG( OPERATION, ERR, "do_syncrepl: "
-                               "ldap_init failed (%s:%s)\n",
-                               si->mastername, si->masterport, 0 );
+               LDAP_LOG( OPERATION, ERR, "do_syncrepl: "
+                       "ldap_initialize failed (%s)\n",
+                       si->masteruri, 0, 0 );
 #else
-                       Debug( LDAP_DEBUG_ANY, "do_syncrepl: "
-                               "ldap_init failed (%s:%s)\n",
-                               si->mastername, si->masterport, 0 );
+               Debug( LDAP_DEBUG_ANY, "do_syncrepl: "
+                       "ldap_initialize failed (%s)\n",
+                       si->masteruri, 0, 0 );
 #endif
-               }
        }
 
        op.o_protocol = LDAP_VERSION3;
@@ -321,9 +365,21 @@ do_syncrepl(
                }
        }
 
+       /* set thread context in syncinfo */
        si->ctx = ctx;
 
-       op.o_tmpmemctx = NULL; /* FIXME : to use per-thread mem context */
+       /* set memory context */
+#if 0
+#define SLAB_SIZE 1048576
+       memsiz = SLAB_SIZE;
+       memctx = sl_mem_create( memsiz, ctx );
+       op.o_tmpmemctx = memctx;
+       op.o_tmpmfuncs = &sl_mfuncs;
+#else
+       op.o_tmpmemctx = NULL;
+       op.o_tmpmfuncs = &ch_mfuncs;
+#endif
+
        op.o_tag = LDAP_REQ_SEARCH;
        op.o_dn = si->updatedn;
        op.o_ndn = si->updatedn;
@@ -382,49 +438,6 @@ do_syncrepl(
 
        psub = be->be_nsuffix[0];
 
-       /* setup LDAP SYNC control */
-       sync_ber = ber_alloc_t( LBER_USE_DER );
-       ber_set_option( sync_ber, LBER_OPT_BER_MEMCTX, op.o_tmpmemctx );
-
-       if ( si->syncCookie ) {
-               ber_printf( sync_ber, "{eO}", abs(si->type), si->syncCookie );
-       } else {
-               ber_printf( sync_ber, "{e}", abs(si->type) );
-       }
-
-       if ( ber_flatten( sync_ber, &sync_bvalp ) == LBER_ERROR ) {
-               ber_free( sync_ber, 1 );
-               return NULL;
-       }
-       ber_free( sync_ber, 1 );
-
-       sctrls = (LDAPControl**) sl_calloc( 3, sizeof(LDAPControl*), op.o_tmpmemctx );
-
-       c[0].ldctl_oid = LDAP_CONTROL_SYNC;
-       c[0].ldctl_value = (*sync_bvalp);
-       c[0].ldctl_iscritical = si->type < 0;
-       sctrls[0] = &c[0];
-
-       if ( si->authzId ) {
-               c[1].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
-               c[1].ldctl_value.bv_val = si->authzId;
-               c[1].ldctl_value.bv_len = strlen( si->authzId );
-               c[1].ldctl_iscritical = 1;
-               sctrls[1] = &c[1];
-       } else {
-               sctrls[1] = NULL;
-       }
-
-       sctrls[2] = NULL;
-
-       err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, sctrls );
-
-       ber_bvfree( sync_bvalp );
-       ch_free( sctrls );
-
-        if ( err != LDAP_OPT_SUCCESS )
-               fprintf( stderr, "Could not set controls : %d\n", err );
-
        /* Delete Attributes */
        if ( si->lastmod == LASTMOD_REQ ) {
                descs = del_descs_lastmod;
@@ -468,16 +481,11 @@ do_syncrepl(
                si->attrs[ n ] = NULL;
        }
 
-       /* Send LDAP SYNC search */
-
-       rc = ldap_search_ext( ld, si->base, si->scope, si->filterstr,
-                               si->attrs, si->attrsonly, NULL, NULL,
-                               NULL, -1, &msgid );
-
-        if( rc != LDAP_SUCCESS ) {
-                fprintf( stderr, "syncrepl: ldap_search_ext: %s (%d)\n",
-                                       ldap_err2string( rc ), rc );
-                return NULL;
+       rc = ldap_sync_search( si, ld, NULL, NULL, &msgid );
+       if( rc != LDAP_SUCCESS ) {
+               fprintf( stderr, "syncrepl: ldap_search_ext: %s (%d)\n",
+                                                       ldap_err2string( rc ), rc );
+               return NULL;
        }
 
        while (( rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ONE, NULL, &res )) > 0 ) {
@@ -488,18 +496,18 @@ do_syncrepl(
                {
                        switch( ldap_msgtype( msg ) ) {
                        case LDAP_RES_SEARCH_ENTRY:
-                               entry = syncrepl_message_to_entry( ld, &op, msg,
+                               entry = syncrepl_message_to_entry( si, ld, &op, msg,
                                        &modlist, &syncstate, &syncUUID, &syncCookie );
-                               rc_efree = syncrepl_entry( ld, &op, entry, modlist,
+                               rc_efree = syncrepl_entry( si, ld, &op, entry, modlist,
                                                syncstate, &syncUUID, &syncCookie, !syncinfo_arrived );
                                if ( syncCookie.bv_len ) {
-                                       syncrepl_updateCookie( ld, &op, &psub, &syncCookie );
+                                       syncrepl_updateCookie( si, ld, &op, &psub, &syncCookie );
                                }
                                if ( rc_efree )
                                        entry_free( entry );
                                for ( ml = modlist; ml != NULL; ml = mlnext ) {
                                        mlnext = ml->sml_next;
-                                       free( ml );
+                                       ber_memfree( ml );
                                }
                                break;
 
@@ -518,11 +526,11 @@ do_syncrepl(
                                if ( rctrls ) {
                                        rctrlp = *rctrls;
                                        ctrl_ber = ber_alloc_t( LBER_USE_DER );
-                                       ber_set_option( ctrl_ber, LBER_OPT_BER_MEMCTX, op.o_tmpmemctx );
+                                       ber_set_option( ctrl_ber, LBER_OPT_BER_MEMCTX, &op.o_tmpmemctx );
                                        ber_write( ctrl_ber, rctrlp->ldctl_value.bv_val, rctrlp->ldctl_value.bv_len, 0 );
                                        ber_reset( ctrl_ber, 1 );
 
-                                       ber_scanf( ctrl_ber, "{" );
+                                       ber_scanf( ctrl_ber, "{" /*"}"*/);
                                        if ( ber_peek_tag( ctrl_ber, &len )
                                                == LDAP_SYNC_TAG_COOKIE ) {
                                                ber_scanf( ctrl_ber, "o", &syncCookie );
@@ -531,8 +539,7 @@ do_syncrepl(
                                if (si->type == LDAP_SYNC_REFRESH_AND_PERSIST) {
                                        if ( cancel_response ) {
                                                if ( syncCookie.bv_len ) {
-                                                       ber_bvfree( si->syncCookie );
-                                                       si->syncCookie = ber_dupbv( NULL, &syncCookie );
+                                                       syncrepl_updateCookie( si, ld, &op, &psub, &syncCookie );
                                                }
                                                if ( ctrl_ber )
                                                        ber_free( ctrl_ber, 1 );
@@ -545,25 +552,25 @@ do_syncrepl(
                                        }
                                } else {
                                        if ( syncCookie.bv_len ) {
-                                               syncrepl_updateCookie( ld, &op, &psub, &syncCookie );
+                                               syncrepl_updateCookie( si, ld, &op, &psub, &syncCookie);
                                        }
-                                       syncrepl_del_nonpresent( ld, &op );
+                                       syncrepl_del_nonpresent( si, ld, &op );
                                        if ( ctrl_ber )
                                                ber_free( ctrl_ber, 1 );
                                        goto done;
                                }
                                break;
 
-                       case LDAP_RES_INTERMEDIATE_RESP:
-                               ldap_parse_intermediate_resp_result( ld, msg,
-                                               &retoid, &retdata, 0 );
-                               if ( !strcmp( retoid, LDAP_SYNC_INFO ) ) {
+                       case LDAP_RES_INTERMEDIATE:
+                               rc = ldap_parse_intermediate( ld, msg,
+                                       &retoid, &retdata, NULL, 0 );
+                               if ( !rc && !strcmp( retoid, LDAP_SYNC_INFO ) ) {
                                        sync_info_arrived = 1;
                                        res_ber = ber_init( retdata );
-                                       ber_scanf( res_ber, "{e", &syncstate );
+                                       ber_scanf( res_ber, "{e" /*"}"*/, &syncstate );
 
                                        if ( syncstate == LDAP_SYNC_REFRESH_DONE ) {
-                                               syncrepl_del_nonpresent( ld, &op );
+                                               syncrepl_del_nonpresent( si, ld, &op );
                                        } else if ( syncstate != LDAP_SYNC_NEW_COOKIE ) {
 #ifdef NEW_LOGGING
                                                LDAP_LOG( OPERATION, ERR,
@@ -576,10 +583,9 @@ do_syncrepl(
 
                                        if ( ber_peek_tag( res_ber, &len )
                                                                == LDAP_SYNC_TAG_COOKIE ) {
-                                               ber_scanf( res_ber, "o}", &syncCookie );
+                                               ber_scanf( res_ber, /*"{"*/ "o}", &syncCookie );
                                                if ( syncCookie.bv_len ) {
-                                                       ber_bvfree( si->syncCookie );
-                                                       si->syncCookie = ber_dupbv( NULL, &syncCookie );
+                                                       syncrepl_updateCookie( si, ld, &op, &psub, &syncCookie);
                                                }
                                        } else {
                                                if ( syncstate == LDAP_SYNC_NEW_COOKIE ) {
@@ -604,8 +610,8 @@ do_syncrepl(
                                                "response\n", 0, 0, 0 );
 #else
                                        Debug( LDAP_DEBUG_ANY, "do_syncrepl : "
-                                               "unknown intermediate "
-                                               "response\n", 0, 0, 0 );
+                                               "unknown intermediate response (%d)\n",
+                                               rc, 0, 0 );
 #endif
                                        ldap_memfree( retoid );
                                        ber_bvfree( retdata );
@@ -659,8 +665,9 @@ done:
        return NULL;
 }
 
-static Entry*
+Entry*
 syncrepl_message_to_entry(
+       syncinfo_t      *si,
        LDAP            *ld,
        Operation       *op,
        LDAPMessage     *msg,
@@ -691,13 +698,13 @@ syncrepl_message_to_entry(
        int             rc;
        char            *a;
 
-       syncinfo_t *si = ( syncinfo_t * ) be->syncinfo;
-
        ber_len_t       len;
        LDAPControl*    rctrlp;
        LDAPControl**   rctrls = NULL;
        BerElement*     ctrl_ber;
 
+       ber_tag_t       tag;
+
        *modlist = NULL;
 
        if ( ldap_msgtype( msg ) != LDAP_RES_SEARCH_ENTRY ) {
@@ -731,10 +738,10 @@ syncrepl_message_to_entry(
 
        e->e_attrs = NULL;
 
-       for ( rc = ldap_get_attribute_ber( ld, msg, ber, &tmp.sml_type, &tmp.sml_bvalues);
-                 rc == LDAP_SUCCESS;
-                 rc = ldap_get_attribute_ber( ld, msg, ber, &tmp.sml_type, &tmp.sml_bvalues))
-       {
+       while ( ber_remaining( ber ) ) {
+               tag = ber_scanf( ber, "{mW}", &tmp.sml_type, &tmp.sml_values );
+
+               if ( tag == LBER_ERROR ) break;
                if ( tmp.sml_type.bv_val == NULL ) break;
 
                mod  = (Modifications *) ch_malloc( sizeof( Modifications ));
@@ -783,7 +790,7 @@ syncrepl_message_to_entry(
        if ( rctrls ) {
                rctrlp = *rctrls;
                ctrl_ber = ber_alloc_t( LBER_USE_DER );
-               ber_set_option( ctrl_ber, LBER_OPT_BER_MEMCTX, op->o_tmpmemctx );
+               ber_set_option( ctrl_ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
                ber_write( ctrl_ber, rctrlp->ldctl_value.bv_val, rctrlp->ldctl_value.bv_len, 0 );
                ber_reset( ctrl_ber, 1 );
                ber_scanf( ctrl_ber, "{eo", syncstate, syncUUID );
@@ -804,6 +811,8 @@ syncrepl_message_to_entry(
        if ( *syncstate == LDAP_SYNC_PRESENT ) {
                e = NULL;
                goto done;
+       } else if ( *syncstate == LDAP_SYNC_DELETE ) {
+               goto done;
        }
 
        if ( *modlist == NULL ) {
@@ -816,7 +825,8 @@ syncrepl_message_to_entry(
 #endif
        }
 
-       rc = slap_mods_check_syncrepl( op, modlist, &text, txtbuf, textlen, NULL );
+       rc = slap_mods_check_syncrepl( si, op, modlist,
+                                                                  &text, txtbuf, textlen, NULL );
 
        if ( rc != LDAP_SUCCESS ) {
 #ifdef NEW_LOGGING
@@ -829,8 +839,8 @@ syncrepl_message_to_entry(
                return NULL;
        }
        
-       rc = slap_mods_opattrs_syncrepl( op, *modlist, modtail,
-                                        &text,txtbuf, textlen );
+       rc = slap_mods_opattrs_syncrepl( si, op, *modlist, modtail,
+                                                                        &text,txtbuf, textlen );
        
        if( rc != LDAP_SUCCESS ) {
 #ifdef NEW_LOGGING
@@ -843,7 +853,7 @@ syncrepl_message_to_entry(
                return NULL;
        }
 
-       rc = slap_mods2entry_syncrepl( *modlist, &e, 1, &text, txtbuf, textlen );
+       rc = slap_mods2entry_syncrepl( si, *modlist, &e, 1, &text, txtbuf, textlen);
        if( rc != LDAP_SUCCESS ) {
 #ifdef NEW_LOGGING
                LDAP_LOG( OPERATION, ERR,
@@ -861,7 +871,7 @@ done:
        return e;
 }
 
-int 
+int
 syncuuid_cmp( const void* v_uuid1, const void* v_uuid2 )
 {
        const struct berval *uuid1 = v_uuid1;
@@ -871,8 +881,9 @@ syncuuid_cmp( const void* v_uuid1, const void* v_uuid2 )
        return ( strcmp( uuid1->bv_val, uuid2->bv_val ) );
 }
 
-static int
+int
 syncrepl_entry(
+       syncinfo_t* si,
        LDAP *ld,
        Operation *op,
        Entry* e,
@@ -884,20 +895,18 @@ syncrepl_entry(
 )
 {
        Backend *be = op->o_bd;
-       syncinfo_t *si = ( syncinfo_t * ) be->syncinfo;
        slap_callback   cb;
        struct berval   csn_bv = {0, NULL};
        struct berval   *syncuuid_bv = NULL;
        char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ];
 
        SlapReply       rs = {REP_RESULT};
-       int rc;
+       int rc = LDAP_SUCCESS;
+
+       struct berval base_bv = {0, NULL};
 
-#if 0 /* FIXME : UUID search required first */
        char *filterstr;
-       struct berval filterstr_bv;
        Filter *filter;
-#endif
 
        Attribute *a;
 
@@ -915,87 +924,111 @@ syncrepl_entry(
                        return 0;
        }
 
-       if ( !attr_find( e->e_attrs, slap_schema.si_ad_entryUUID )) {
-               attr_merge_one( e, slap_schema.si_ad_entryUUID, syncUUID, syncUUID );
-       }
-
-#if 0 /* FIXME : UUID search required first */
-       filterstr = (char *) sl_malloc( strlen("entryUUID=") + syncUUID->bv_len + 1, op->o_tmpmemctx ); 
+       filterstr = (char *) sl_malloc( strlen("entryUUID=") + syncUUID->bv_len + 1,
+                                                                       op->o_tmpmemctx ); 
        strcpy( filterstr, "entryUUID=" );
        strcat( filterstr, syncUUID->bv_val );
-#endif
 
        si->e = e;
        si->syncUUID = syncUUID;
+       si->syncUUID_ndn = NULL;
 
-#if 0 /* FIXME : UUID search required first */
        filter = str2filter( filterstr );
-       ber_str2bv( filterstr, strlen(filterstr), 1, &filterstr_bv );
+       ber_str2bv( filterstr, strlen(filterstr), 1, &op->ors_filterstr );
        ch_free( filterstr );
-#endif
+       op->ors_filter = filter;
+       op->ors_scope = LDAP_SCOPE_SUBTREE;
 
-       op->o_req_dn = e->e_name;
-       op->o_req_ndn = e->e_nname;
+       /* get syncrepl cookie of shadow replica from subentry */
+       ber_str2bv( si->base, strlen(si->base), 1, &base_bv ); 
+       dnPrettyNormal( 0, &base_bv, &op->o_req_dn, &op->o_req_ndn, op->o_tmpmemctx );
+       ch_free( base_bv.bv_val );
 
+       /* set callback function */
        op->o_callback = &cb;
+       cb.sc_response = dn_callback;
+       cb.sc_private = si;
+
+       be->be_search( op, &rs );
+
+       ch_free( op->o_req_dn.bv_val );
+       ch_free( op->o_req_ndn.bv_val );
+       filter_free( op->ors_filter );
+       ch_free( op->ors_filterstr.bv_val );
+
        cb.sc_response = null_callback;
        cb.sc_private = si;
 
+       rc = LDAP_SUCCESS;
+
+       if ( si->syncUUID_ndn ) {
+               op->o_req_dn = *si->syncUUID_ndn;
+               op->o_req_ndn = *si->syncUUID_ndn;
+               op->o_tag = LDAP_REQ_DELETE;
+               rc = be->be_delete( op, &rs );
+       }
+
        switch ( syncstate ) {
        case LDAP_SYNC_ADD :
        case LDAP_SYNC_MODIFY :
-sync_add_retry:
-               op->o_tag = LDAP_REQ_MODIFY;
-               op->orm_modlist = modlist;
-               rc = be->be_modify( op, &rs );
-               if ( rc != LDAP_SUCCESS ) {
-                       if ( rc == LDAP_REFERRAL ||
-                                rc == LDAP_NO_SUCH_OBJECT ||
-                                rc == DB_NOTFOUND ) {
-                               op->o_tag = LDAP_REQ_ADD;
-                               op->ora_e = e;
-                               rc = be->be_add( op, &rs );
-                               if ( rc != LDAP_SUCCESS ) {
-                                       if ( rc == LDAP_ALREADY_EXISTS ) {
-                                               goto sync_add_retry;
-                                       } else if ( rc == LDAP_REFERRAL ||
-                                                               rc == LDAP_NO_SUCH_OBJECT ||
-                                                               rc == DB_NOTFOUND ) {
-                                               syncrepl_add_glue(ld, op, e,
-                                                       modlist, syncstate,
-                                                       syncUUID, syncCookie);
-                                       } else {
+
+               if ( rc == LDAP_SUCCESS ||
+                        rc == LDAP_REFERRAL ||
+                        rc == LDAP_NO_SUCH_OBJECT ) {
+
+                       if ( !attr_find( e->e_attrs, slap_schema.si_ad_entryUUID )) {
+                               attr_merge_one( e, slap_schema.si_ad_entryUUID, syncUUID, syncUUID );
+                       }
+
+                       op->o_tag = LDAP_REQ_ADD;
+                       op->ora_e = e;
+                       op->o_req_dn = e->e_name;
+                       op->o_req_ndn = e->e_nname;
+                       rc = be->be_add( op, &rs );
+
+                       if ( rc != LDAP_SUCCESS ) {
+                               if ( rc == LDAP_ALREADY_EXISTS ) {      
+                                       op->o_tag = LDAP_REQ_MODIFY;
+                                       op->orm_modlist = modlist;
+                                       op->o_req_dn = e->e_name;
+                                       op->o_req_ndn = e->e_nname;
+                                       rc = be->be_modify( op, &rs );
+                               } else if ( rc == LDAP_REFERRAL ||
+                                                       rc == LDAP_NO_SUCH_OBJECT ) {
+                                       syncrepl_add_glue( si, ld, op, e,
+                                               modlist, syncstate,
+                                               syncUUID, syncCookie);
+                               } else {
 #ifdef NEW_LOGGING
-                                               LDAP_LOG( OPERATION, ERR,
-                                                       "be_add failed (%d)\n",
-                                                       rc, 0, 0 );
+                                       LDAP_LOG( OPERATION, ERR,
+                                               "be_modify failed (%d)\n",
+                                               rc, 0, 0 );
 #else
-                                               Debug( LDAP_DEBUG_ANY,
-                                                       "be_add failed (%d)\n",
-                                                       rc, 0, 0 );
+                                       Debug( LDAP_DEBUG_ANY,
+                                               "be_modify failed (%d)\n",
+                                               rc, 0, 0 );
 #endif
-                                       }
-                               } else {
-                                       return 0;
                                }
                        } else {
+                               return 0;
+                       }
+               } else {
 #ifdef NEW_LOGGING
-                               LDAP_LOG( OPERATION, ERR,
-                                       "be_modify failed (%d)\n", rc, 0, 0 );
+                       LDAP_LOG( OPERATION, ERR,
+                               "be_modify/be_delete failed (%d)\n", rc, 0, 0 );
 #else
-                               Debug( LDAP_DEBUG_ANY,
-                                       "be_modify failed (%d)\n", rc, 0, 0 );
+                       Debug( LDAP_DEBUG_ANY,
+                               "be_modify/be_delete failed (%d)\n", rc, 0, 0 );
 #endif
-                       }
                }
 
                si->e = NULL;
                return 1;
+
        case LDAP_SYNC_DELETE :
-               op->o_tag = LDAP_REQ_DELETE;
-               be->be_delete( op, &rs );
-               si->e = NULL;
+               /* Already deleted */
                return 1;
+
        default :
 #ifdef NEW_LOGGING
                LDAP_LOG( OPERATION, ERR,
@@ -1008,14 +1041,14 @@ sync_add_retry:
        }
 }
 
-static int
+static void
 syncrepl_del_nonpresent(
+       syncinfo_t *si,
        LDAP *ld,
        Operation *op
 )
 {
        Backend* be = op->o_bd;
-       syncinfo_t *si = ( syncinfo_t * ) be->syncinfo;
        slap_callback   cb;
        struct berval   base_bv = {0, NULL};
        Filter *filter;
@@ -1072,11 +1105,14 @@ syncrepl_del_nonpresent(
                ch_free( op->o_req_ndn.bv_val );
        filter_free( op->ors_filter );
        ch_free( op->ors_filterstr.bv_val );
+
+       return;
 }
 
 
 static void
 syncrepl_add_glue(
+       syncinfo_t *si,
        LDAP *ld,
        Operation* op,
        Entry *e,
@@ -1087,7 +1123,6 @@ syncrepl_add_glue(
 )
 {
        Backend *be = op->o_bd;
-       syncinfo_t *si = op->o_callback->sc_private;
        struct berval   uuid_bv = {0, NULL};
        slap_callback cb;
        Attribute       *a;
@@ -1184,8 +1219,9 @@ syncrepl_add_glue(
        return;
 }
 
-static void
+void
 syncrepl_updateCookie(
+       syncinfo_t *si,
        LDAP *ld,
        Operation *op,
        struct berval *pdn,
@@ -1193,7 +1229,6 @@ syncrepl_updateCookie(
 )
 {
        Backend *be = op->o_bd;
-       syncinfo_t *si = ( syncinfo_t * ) be->syncinfo;
        Modifications *ml;
        Modifications *mlnext;
        Modifications *mod;
@@ -1291,7 +1326,8 @@ syncrepl_updateCookie(
        *modtail = mod;
        modtail = &mod->sml_next;
 
-       rc = slap_mods_check_syncrepl( op, &modlist, &text, txtbuf, textlen, NULL );
+       rc = slap_mods_check_syncrepl( si, op, &modlist,
+                                                                  &text, txtbuf, textlen, NULL );
 
        if ( rc != LDAP_SUCCESS ) {
 #ifdef NEW_LOGGING
@@ -1304,7 +1340,8 @@ syncrepl_updateCookie(
        }
 
        op->o_tag = LDAP_REQ_ADD;
-       rc = slap_mods_opattrs_syncrepl( op, modlist, modtail, &text,txtbuf, textlen );
+       rc = slap_mods_opattrs_syncrepl( si, op, modlist, modtail,
+                                                                        &text,txtbuf, textlen );
 
        if( rc != LDAP_SUCCESS ) {
 #ifdef NEW_LOGGING
@@ -1325,7 +1362,7 @@ syncrepl_updateCookie(
 
        e->e_attrs = NULL;
 
-       rc = slap_mods2entry_syncrepl( modlist, &e, 1, &text, txtbuf, textlen );
+       rc = slap_mods2entry_syncrepl( si, modlist, &e, 1, &text, txtbuf, textlen );
 
        if( rc != LDAP_SUCCESS ) {
 #ifdef NEW_LOGGING
@@ -1351,8 +1388,7 @@ update_cookie_retry:
        rc = be->be_modify( op, &rs );
        if ( rc != LDAP_SUCCESS ) {
                if ( rc == LDAP_REFERRAL ||
-                        rc == LDAP_NO_SUCH_OBJECT ||
-                        rc == DB_NOTFOUND ) {
+                        rc == LDAP_NO_SUCH_OBJECT ) {
                        op->o_tag = LDAP_REQ_ADD;
                        op->ora_e = e;
                        rc = be->be_add( op, &rs );
@@ -1360,8 +1396,7 @@ update_cookie_retry:
                                if ( rc == LDAP_ALREADY_EXISTS ) {
                                        goto update_cookie_retry;
                                } else if ( rc == LDAP_REFERRAL ||
-                                                       rc == LDAP_NO_SUCH_OBJECT ||
-                                                       rc == DB_NOTFOUND ) {
+                                                       rc == LDAP_NO_SUCH_OBJECT ) {
 #ifdef NEW_LOGGING
                                        LDAP_LOG( OPERATION, ERR,
                                                "cookie will be non-persistent\n",
@@ -1412,6 +1447,7 @@ done :
 
 static
 int slap_mods_check_syncrepl(
+       syncinfo_t* si,
        Operation *op,
        Modifications **mlp,
        const char **text,
@@ -1421,7 +1457,6 @@ int slap_mods_check_syncrepl(
 {
        int rc;
        Backend *be = op->o_bd;
-       syncinfo_t *si = ( syncinfo_t * ) be->syncinfo;
        AttributeDescription** descs;
        int i;
        Modifications *prevml = NULL;
@@ -1603,6 +1638,7 @@ int slap_mods_check_syncrepl(
 
 static
 int slap_mods_opattrs_syncrepl(
+       syncinfo_t *si,
        Operation *op,
        Modifications *mods,
        Modifications **modtail,
@@ -1617,7 +1653,6 @@ int slap_mods_opattrs_syncrepl(
        char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ];
        Modifications *mod;
        Backend *be = op->o_bd;
-       syncinfo_t *si = ( syncinfo_t * ) be->syncinfo;
 
        int mop = LDAP_MOD_REPLACE;
 
@@ -1762,6 +1797,7 @@ int slap_mods_opattrs_syncrepl(
 
 static
 int slap_mods2entry_syncrepl(
+       syncinfo_t *si,
        Modifications *mods,
        Entry **e,
        int repl_user,
@@ -1916,6 +1952,21 @@ cookie_callback(
        return LDAP_SUCCESS;
 }
 
+static int
+dn_callback(
+       Operation*      op,
+       SlapReply*      rs
+)
+{
+       syncinfo_t *si = op->o_callback->sc_private;
+       
+       if ( rs->sr_type == REP_SEARCH ) {
+               si->syncUUID_ndn = &rs->sr_entry->e_nname;
+       }
+
+       return LDAP_SUCCESS;
+}
+
 static int
 nonpresent_callback(
        Operation*      op,
@@ -1964,11 +2015,12 @@ null_callback(
        SlapReply*      rs
 )
 {
+       syncinfo_t *si = op->o_callback->sc_private;
+
        if ( rs->sr_err != LDAP_SUCCESS &&
                 rs->sr_err != LDAP_REFERRAL &&
                 rs->sr_err != LDAP_ALREADY_EXISTS &&
-                rs->sr_err != LDAP_NO_SUCH_OBJECT &&
-                rs->sr_err != DB_NOTFOUND ) {
+                rs->sr_err != LDAP_NO_SUCH_OBJECT ) {
 #ifdef NEW_LOGGING
                LDAP_LOG( OPERATION, ERR,
                        "null_callback : error code 0x%x\n",
@@ -1982,4 +2034,44 @@ null_callback(
        return LDAP_SUCCESS;
 }
 
+
+char **
+str2clist( char **out, char *in, const char *brkstr )
+{
+       char    *str;
+       char    *s;
+       char    *lasts;
+       int     i, j;
+       const char *text;
+       char    **new;
+
+       /* find last element in list */
+       for (i = 0; out && out[i]; i++);
+       
+       /* protect the input string from strtok */
+       str = ch_strdup( in );
+
+       /* Count words in string */
+       j=1;
+       for ( s = str; *s; s++ ) {
+               if ( strchr( brkstr, *s ) != NULL ) {
+                       j++;
+               }
+       }
+
+       out = ch_realloc( out, ( i + j + 1 ) * sizeof( char * ) );
+       new = out + i;
+       for ( s = ldap_pvt_strtok( str, brkstr, &lasts );
+               s != NULL;
+               s = ldap_pvt_strtok( NULL, brkstr, &lasts ) )
+       {
+               *new = ch_strdup( s );
+               new++;
+       }
+
+       *new = NULL;
+       free( str );
+       return( out );
+}
+
 #endif