X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fsyncrepl.c;h=627e43a3d2e5458d9f46fea7121e4e10ce2937de;hb=e8d95fa072d7fc1b2f0ca485bb8278790870bda2;hp=e6a9a43f7f49d556a39a7f80e76c881ac881d366;hpb=6a56c7014c9d9c1d8f7a7dab9a60f3c9f83f7792;p=openldap diff --git a/servers/slapd/syncrepl.c b/servers/slapd/syncrepl.c index e6a9a43f7f..627e43a3d2 100644 --- a/servers/slapd/syncrepl.c +++ b/servers/slapd/syncrepl.c @@ -41,6 +41,7 @@ typedef struct cookie_state { ldap_pvt_thread_mutex_t cs_mutex; int cs_num; int cs_age; + int cs_ref; struct berval *cs_vals; int *cs_sids; } cookie_state; @@ -1255,13 +1256,15 @@ do_syncrepl( int rc = LDAP_SUCCESS; int dostop = 0; ber_socket_t s; - int i, defer = 1, fail = 0; + int i, defer = 1, fail = 0, freeinfo = 0; Backend *be; - Debug( LDAP_DEBUG_TRACE, "=>do_syncrepl %s\n", si->si_ridtxt, 0, 0 ); - if ( si == NULL ) return NULL; + if ( slapd_shutdown ) + return NULL; + + Debug( LDAP_DEBUG_TRACE, "=>do_syncrepl %s\n", si->si_ridtxt, 0, 0 ); /* Don't get stuck here while a pause is initiated */ while ( ldap_pvt_thread_mutex_trylock( &si->si_mutex )) { @@ -1271,6 +1274,10 @@ do_syncrepl( ldap_pvt_thread_yield(); } + if ( si->si_ctype < 1 ) { + goto deleted; + } + switch( abs( si->si_type ) ) { case LDAP_SYNC_REFRESH_ONLY: case LDAP_SYNC_REFRESH_AND_PERSIST: @@ -1296,10 +1303,6 @@ do_syncrepl( connection_fake_init( &conn, &opbuf, ctx ); op = &opbuf.ob_op; - /* use global malloc for now */ - op->o_tmpmemctx = NULL; - op->o_tmpmfuncs = &ch_mfuncs; - op->o_managedsait = SLAP_CONTROL_NONCRITICAL; be = si->si_be; @@ -1358,8 +1361,13 @@ reload: goto reload; } +deleted: /* We got deleted while running on cn=config */ - if ( !si->si_ctype ) { + if ( si->si_ctype < 1 ) { + if ( si->si_ctype == -1 ) { + si->si_ctype = 0; + freeinfo = 1; + } if ( si->si_conn ) dostop = 1; rc = -1; @@ -1426,7 +1434,7 @@ reload: break; } - if ( !si->si_ctype + if ( si->si_ctype < 1 || !si->si_retrynum || si->si_retrynum[i] == RETRYNUM_TAIL ) { if ( si->si_re ) { ldap_pvt_runqueue_remove( &slapd_rq, rtask ); @@ -1449,24 +1457,22 @@ reload: if ( rc ) { if ( fail == RETRYNUM_TAIL ) { Debug( LDAP_DEBUG_ANY, - "do_syncrepl: %s quitting\n", - si->si_ridtxt, 0, 0 ); + "do_syncrepl: %s rc %d quitting\n", + si->si_ridtxt, rc, 0 ); } else if ( fail > 0 ) { Debug( LDAP_DEBUG_ANY, - "do_syncrepl: %s retrying (%d retries left)\n", - si->si_ridtxt, fail, 0 ); + "do_syncrepl: %s rc %d retrying (%d retries left)\n", + si->si_ridtxt, rc, fail ); } else { Debug( LDAP_DEBUG_ANY, - "do_syncrepl: %s retrying\n", - si->si_ridtxt, 0, 0 ); + "do_syncrepl: %s rc %d retrying\n", + si->si_ridtxt, rc, 0 ); } } /* Do final delete cleanup */ - if ( !si->si_ctype ) { - cookie_state *cs = si->si_cookieState; - syncinfo_free( si, ( !be->be_syncinfo || - be->be_syncinfo->si_cookieState != cs )); + if ( freeinfo ) { + syncinfo_free( si, 0 ); } return NULL; } @@ -1621,7 +1627,16 @@ syncrepl_message_to_op( if ( !ber_bvstrcasecmp( &bv, &ls->ls_dn ) ) { bdn = bvals[0]; - dnPrettyNormal( NULL, &bdn, &dn, &ndn, op->o_tmpmemctx ); + rc = dnPrettyNormal( NULL, &bdn, &dn, &ndn, op->o_tmpmemctx ); + if ( rc != LDAP_SUCCESS ) { + Debug( LDAP_DEBUG_ANY, + "syncrepl_message_to_op: %s " + "dn \"%s\" normalization failed (%d)", + si->si_ridtxt, bdn.bv_val, rc ); + rc = -1; + ch_free( bvals ); + goto done; + } ber_dupbv( &op->o_req_dn, &dn ); ber_dupbv( &op->o_req_ndn, &ndn ); slap_sl_free( ndn.bv_val, op->o_tmpmemctx ); @@ -1853,7 +1868,21 @@ syncrepl_message_to_entry( return -1; } - dnPrettyNormal( NULL, &bdn, &dn, &ndn, op->o_tmpmemctx ); + rc = dnPrettyNormal( NULL, &bdn, &dn, &ndn, op->o_tmpmemctx ); + if ( rc != LDAP_SUCCESS ) { + /* One of the things that could happen is that the schema + * is not lined-up; this could result in unknown attributes. + * A value non conformant to the syntax should be unlikely, + * except when replicating between different versions + * of the software, or when syntax validation bugs are fixed + */ + Debug( LDAP_DEBUG_ANY, + "syncrepl_message_to_entry: " + "%s dn \"%s\" normalization failed (%d)", + si->si_ridtxt, bdn.bv_val, rc ); + return rc; + } + ber_dupbv( &op->o_req_dn, &dn ); ber_dupbv( &op->o_req_ndn, &ndn ); slap_sl_free( ndn.bv_val, op->o_tmpmemctx ); @@ -2181,8 +2210,8 @@ retry_add:; rc = op->o_bd->be_add( op, &rs_add ); Debug( LDAP_DEBUG_SYNC, - "syncrepl_entry: %s be_add (%d)\n", - si->si_ridtxt, rc, 0 ); + "syncrepl_entry: %s be_add %s (%d)\n", + si->si_ridtxt, op->o_req_dn.bv_val, rc ); switch ( rs_add.sr_err ) { case LDAP_SUCCESS: if ( op->ora_e == entry ) { @@ -2244,8 +2273,8 @@ retry_add:; default: Debug( LDAP_DEBUG_ANY, - "syncrepl_entry: %s be_add failed (%d)\n", - si->si_ridtxt, rs_add.sr_err, 0 ); + "syncrepl_entry: %s be_add %s failed (%d)\n", + si->si_ridtxt, op->o_req_dn.bv_val, rs_add.sr_err ); break; } syncCSN = NULL; @@ -2384,7 +2413,7 @@ retry_add:; } } } - + /* RDNs must be NUL-terminated for back-ldap */ noldp = op->orr_newrdn; ber_dupbv_x( &op->orr_newrdn, &noldp, op->o_tmpmemctx ); @@ -2441,8 +2470,8 @@ retry_add:; slap_mods_free( op->orr_modlist, 1 ); Debug( LDAP_DEBUG_SYNC, - "syncrepl_entry: %s be_modrdn (%d)\n", - si->si_ridtxt, rc, 0 ); + "syncrepl_entry: %s be_modrdn %s (%d)\n", + si->si_ridtxt, op->o_req_dn.bv_val, rc ); op->o_bd = be; /* Renamed entries may still have other mods so just fallthru */ op->o_req_dn = entry->e_name; @@ -2463,8 +2492,8 @@ retry_add:; slap_mods_free( op->orm_modlist, 1 ); op->orm_no_opattrs = 0; Debug( LDAP_DEBUG_SYNC, - "syncrepl_entry: %s be_modify (%d)\n", - si->si_ridtxt, rc, 0 ); + "syncrepl_entry: %s be_modify %s (%d)\n", + si->si_ridtxt, op->o_req_dn.bv_val, rc ); if ( rs_modify.sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "syncrepl_entry: %s be_modify failed (%d)\n", @@ -2490,8 +2519,8 @@ retry_add:; op->o_bd = si->si_wbe; rc = op->o_bd->be_delete( op, &rs_delete ); Debug( LDAP_DEBUG_SYNC, - "syncrepl_entry: %s be_delete (%d)\n", - si->si_ridtxt, rc, 0 ); + "syncrepl_entry: %s be_delete %s (%d)\n", + si->si_ridtxt, op->o_req_dn.bv_val, rc ); while ( rs_delete.sr_err == LDAP_SUCCESS && op->o_delete_glue_parent ) { @@ -3596,12 +3625,9 @@ syncinfo_free( syncinfo_t *sie, int free_all ) { syncinfo_t *si_next; - if ( free_all && sie->si_cookieState ) { - ch_free( sie->si_cookieState->cs_sids ); - ber_bvarray_free( sie->si_cookieState->cs_vals ); - ldap_pvt_thread_mutex_destroy( &sie->si_cookieState->cs_mutex ); - ch_free( sie->si_cookieState ); - } + Debug( LDAP_DEBUG_TRACE, "syncinfo_free: %s\n", + sie->si_ridtxt, 0, 0 ); + do { si_next = sie->si_next; @@ -3613,20 +3639,21 @@ syncinfo_free( syncinfo_t *sie, int free_all ) ldap_unbind_ext( sie->si_ld, NULL, NULL ); } - /* re-fetch it, in case it was already removed */ - ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); - sie->si_re = ldap_pvt_runqueue_find( &slapd_rq, do_syncrepl, sie ); if ( sie->si_re ) { - if ( ldap_pvt_runqueue_isrunning( &slapd_rq, sie->si_re ) ) - ldap_pvt_runqueue_stoptask( &slapd_rq, sie->si_re ); - ldap_pvt_runqueue_remove( &slapd_rq, sie->si_re ); + struct re_s *re = sie->si_re; + sie->si_re = NULL; + + ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); + if ( ldap_pvt_runqueue_isrunning( &slapd_rq, re ) ) + ldap_pvt_runqueue_stoptask( &slapd_rq, re ); + ldap_pvt_runqueue_remove( &slapd_rq, re ); + ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex ); } - - ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex ); - ldap_pvt_thread_mutex_destroy( &sie->si_mutex ); - + + ldap_pvt_thread_mutex_destroy( &sie->si_mutex ); + bindconf_free( &sie->si_bindconf ); - + if ( sie->si_filterstr.bv_val ) { ch_free( sie->si_filterstr.bv_val ); } @@ -3702,6 +3729,13 @@ syncinfo_free( syncinfo_t *sie, int free_all ) } ch_free( npe ); } + sie->si_cookieState->cs_ref--; + if ( !sie->si_cookieState->cs_ref ) { + ch_free( sie->si_cookieState->cs_sids ); + ber_bvarray_free( sie->si_cookieState->cs_vals ); + ldap_pvt_thread_mutex_destroy( &sie->si_cookieState->cs_mutex ); + ch_free( sie->si_cookieState ); + } ch_free( sie ); sie = si_next; } while ( free_all && si_next ); @@ -4298,6 +4332,8 @@ add_syncrepl( rc = parse_syncrepl_line( c, si ); if ( rc == 0 ) { + LDAPURLDesc *lud; + /* Must be LDAPv3 because we need controls */ switch ( si->si_bindconf.sb_version ) { case 0: @@ -4315,24 +4351,35 @@ add_syncrepl( return 1; } + if ( ldap_url_parse( si->si_bindconf.sb_uri.bv_val, &lud )) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "<%s> invalid URL", c->argv[0] ); + Debug( LDAP_DEBUG_ANY, "%s: %s %s\n", + c->log, c->cr_msg, si->si_bindconf.sb_uri.bv_val ); + return 1; + } + si->si_be = c->be; if ( slapMode & SLAP_SERVER_MODE ) { - Listener **l = slapd_get_listeners(); int isMe = 0; - - /* check if URL points to current server. If so, ignore - * this configuration. We require an exact match. Just - * in case they really want to do this, they can vary - * the case of the URL to allow it. + /* check if consumer points to current server and database. + * If so, ignore this configuration. */ - if ( l && !SLAP_DBHIDDEN( c->be ) ) { + if ( !SLAP_DBHIDDEN( c->be ) ) { int i; - for ( i=0; l[i]; i++ ) { - if ( bvmatch( &l[i]->sl_url, &si->si_bindconf.sb_uri ) ) { + /* if searchbase doesn't match current DB suffix, + * assume it's different + */ + for ( i=0; !BER_BVISNULL( &c->be->be_nsuffix[i] ); i++ ) { + if ( bvmatch( &si->si_base, &c->be->be_nsuffix[i] )) { isMe = 1; break; } } + /* if searchbase matches, see if URLs match */ + if ( isMe && config_check_my_url( si->si_bindconf.sb_uri.bv_val, + lud ) == NULL ) + isMe = 0; } if ( !isMe ) { @@ -4351,6 +4398,7 @@ add_syncrepl( /* mirrormode still needs to see this flag in tool mode */ rc = config_sync_shadow( c ) ? -1 : 0; } + ldap_free_urldesc( lud ); } #ifdef HAVE_TLS @@ -4371,7 +4419,7 @@ add_syncrepl( si->si_cookieState = c->be->be_syncinfo->si_cookieState; - // add new syncrepl to end of list (same order as when deleting) + /* add new syncrepl to end of list (same order as when deleting) */ for ( sip = c->be->be_syncinfo; sip->si_next; sip = sip->si_next ); sip->si_next = si; } else { @@ -4380,6 +4428,7 @@ add_syncrepl( c->be->be_syncinfo = si; } + si->si_cookieState->cs_ref++; si->si_next = NULL; @@ -4578,13 +4627,11 @@ syncrepl_config( ConfigArgs *c ) } return 1; } else if ( c->op == LDAP_MOD_DELETE ) { - cookie_state *cs = NULL; int isrunning = 0; if ( c->be->be_syncinfo ) { syncinfo_t *si, **sip; int i; - cs = c->be->be_syncinfo->si_cookieState; for ( sip = &c->be->be_syncinfo, i=0; *sip; i++ ) { si = *sip; if ( c->valx == -1 || i == c->valx ) { @@ -4597,11 +4644,20 @@ syncrepl_config( ConfigArgs *c ) if ( ldap_pvt_thread_mutex_trylock( &si->si_mutex )) { isrunning = 1; } else { + if ( si->si_conn ) { + /* If there's a persistent connection, it may + * already have a thread queued. We know it's + * not active, so it must be pending and we + * can simply cancel it now. + */ + ldap_pvt_thread_pool_retract( &connection_pool, + si->si_re->routine, si->si_re ); + } ldap_pvt_thread_mutex_unlock( &si->si_mutex ); } } - if ( si->si_re && isrunning ) { - si->si_ctype = 0; + if ( isrunning ) { + si->si_ctype = -1; si->si_next = NULL; } else { syncinfo_free( si, 0 ); @@ -4615,12 +4671,6 @@ syncrepl_config( ConfigArgs *c ) } if ( !c->be->be_syncinfo ) { SLAP_DBFLAGS( c->be ) &= ~SLAP_DBFLAG_SHADOW_MASK; - if ( cs && !isrunning ) { - ch_free( cs->cs_sids ); - ber_bvarray_free( cs->cs_vals ); - ldap_pvt_thread_mutex_destroy( &cs->cs_mutex ); - ch_free( cs ); - } } return 0; }