diff options
author | David Boreham <dboreham@redhat.com> | 2005-03-31 22:00:46 +0000 |
---|---|---|
committer | David Boreham <dboreham@redhat.com> | 2005-03-31 22:00:46 +0000 |
commit | ff2e6525088908ba32f727d92f0ea861b1cfa0b4 (patch) | |
tree | eb2f3fa50a44bf4b9e24fa9ed6221827c7efdf41 /ldap/servers/plugins/replication/windows_inc_protocol.c | |
parent | 3e4f39cde6b1e1fa0395c2f7bce0e13eaa0ead88 (diff) | |
download | ds-ff2e6525088908ba32f727d92f0ea861b1cfa0b4.tar.gz ds-ff2e6525088908ba32f727d92f0ea861b1cfa0b4.tar.xz ds-ff2e6525088908ba32f727d92f0ea861b1cfa0b4.zip |
New windows sync code
Diffstat (limited to 'ldap/servers/plugins/replication/windows_inc_protocol.c')
-rw-r--r-- | ldap/servers/plugins/replication/windows_inc_protocol.c | 1982 |
1 files changed, 567 insertions, 1415 deletions
diff --git a/ldap/servers/plugins/replication/windows_inc_protocol.c b/ldap/servers/plugins/replication/windows_inc_protocol.c index 1de3fb2a..f588d6ba 100644 --- a/ldap/servers/plugins/replication/windows_inc_protocol.c +++ b/ldap/servers/plugins/replication/windows_inc_protocol.c @@ -32,59 +32,6 @@ Perhaps these events should be properties of the main protocol. #include "slapi-plugin.h" extern int slapi_log_urp; -typedef struct attribute_map -{ - char *old_name; - char *new_name; - int map_to; - -} attribute_map; - -static attribute_map mapping[] = -{ /* map the attribute from , to, which platform we going to? */ - { "ntUserDomainId", "sAMAccountName", REPLICA_TYPE_WINDOWS}, - { "ntUserHomeDir", "homeDirectory", REPLICA_TYPE_WINDOWS}, - { "ntUserScriptPath", "scriptPath", REPLICA_TYPE_WINDOWS}, - { "ntUserLastLogon", "lastLogon", REPLICA_TYPE_WINDOWS}, - { "ntUserLastLogoff", "lastLogoff", REPLICA_TYPE_WINDOWS}, - { "cn", "description", REPLICA_TYPE_WINDOWS}, /* temporary */ - { "uid", "cn", REPLICA_TYPE_WINDOWS}, - { "dn", "dn", REPLICA_TYPE_WINDOWS}, - { "sn", "sn", REPLICA_TYPE_WINDOWS}, - - { "sAMAccountName", "ntUserDomainId", REPLICA_TYPE_MULTIMASTER}, - { "homeDirectory", "ntUserHomeDir", REPLICA_TYPE_MULTIMASTER}, - { "scriptPath", "ntUserScriptPath", REPLICA_TYPE_MULTIMASTER}, - { "lastLogon", "ntUserLastLogon", REPLICA_TYPE_MULTIMASTER}, - { "lastLogoff", "ntUserLastLogoff", REPLICA_TYPE_MULTIMASTER}, - { "sAMAccountName", "uid", REPLICA_TYPE_MULTIMASTER}, - { "dn", "dn", REPLICA_TYPE_MULTIMASTER}, - { "sAMAccountName", "sn", REPLICA_TYPE_MULTIMASTER}, - { "sAMAccountName", "cn", REPLICA_TYPE_MULTIMASTER}, - - {NULL, NULL, -1} -}; - -static attribute_map group_map[] = -{ - { "ntGroupDomainId ", "name", REPLICA_TYPE_WINDOWS}, - { "ntGroupDomainId ", "sAMAccountName", REPLICA_TYPE_WINDOWS}, - { "ntGroupType", "groupType", REPLICA_TYPE_WINDOWS}, - - { "sAMAccountName", "ntGroupDomainId ", REPLICA_TYPE_MULTIMASTER}, - { "groupType", "ntGroupType", REPLICA_TYPE_MULTIMASTER}, - - {NULL, NULL, -1} - -}; - -void map_entry_user(Slapi_Entry **e, int map_to, char** password); -static Slapi_Entry* windows_entry_already_exists(Slapi_Entry *e); - -static Slapi_DN* map_dn_user(Slapi_DN *sdn, int map_to, const Slapi_DN *root); -static Slapi_DN* map_dn_group(Slapi_DN *sdn, int map_to, const Slapi_DN *root); -static void make_mods_from_entries(Slapi_Entry *new_entry, Slapi_Entry *existing_entry, LDAPMod ***attrs); -static void alter_mods(LDAPMod ***m, char** password); /*** from proto-slap.h ***/ void ava_done(struct ava *ava); @@ -119,6 +66,7 @@ typedef struct windows_inc_private #define EVENT_REPLICATE_NOW 16 #define EVENT_PROTOCOL_SHUTDOWN 32 #define EVENT_AGMT_CHANGED 64 +#define EVENT_RUN_DIRSYNC 128 #define UPDATE_NO_MORE_UPDATES 201 #define UPDATE_TRANSIENT_ERROR 202 @@ -142,7 +90,11 @@ typedef struct windows_inc_private * we go ahead and start a replication session, just to be safe */ #define MAX_WAIT_BETWEEN_SESSIONS PR_SecondsToInterval(60 * 5) /* 5 minutes */ - +/* + * Periodic synchronization interval. This is used for scheduling the periodic_dirsync event. + * The time is in milliseconds. + */ +#define PERIODIC_DIRSYNC_INTERVAL 5 * 60 * 1000 /* DBDB this should probably be configurable. 5 mins fixed for now */ /* * tests if the protocol has been shutdown and we need to quit * event_occurred resets the bits in the bit flag, so whoever tests for shutdown @@ -161,8 +113,10 @@ static int windows_examine_update_vector(Private_Repl_Protocol *prp, RUV *ruv); static PRBool ignore_error_and_keep_going(int error); static const char* state2name (int state); static const char* event2name (int event); -static const char* op2string (int op); +static const char* acquire2name (int code); +static void periodic_dirsync(time_t when, void *arg); +static Slapi_Eq_Context dirsync; /* * It's specifically ok to delete a protocol instance that * is currently running. The instance will be shut down, and @@ -172,14 +126,18 @@ static const char* op2string (int op); static void windows_inc_delete(Private_Repl_Protocol **prpp) { + LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_inc_delete\n", 0, 0, 0 ); /* First, stop the protocol if it isn't already stopped */ /* Then, delete all resources used by the protocol */ + slapi_eq_cancel(dirsync); + LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_inc_delete\n", 0, 0, 0 ); } /* helper function */ void w_set_pause_and_busy_time(long *pausetime, long *busywaittime) { + LDAPDebug( LDAP_DEBUG_TRACE, "=> w_set_pause_and_busy_time\n", 0, 0, 0 ); /* If neither are set, set busy time to its default */ if (!*pausetime && !*busywaittime) { @@ -216,6 +174,7 @@ w_set_pause_and_busy_time(long *pausetime, long *busywaittime) */ *pausetime = *busywaittime + 1; } + LDAPDebug( LDAP_DEBUG_TRACE, "<= w_set_pause_and_busy_time\n", 0, 0, 0 ); } /* @@ -267,435 +226,472 @@ w_set_pause_and_busy_time(long *pausetime, long *busywaittime) static void windows_inc_run(Private_Repl_Protocol *prp) { - int current_state = STATE_START; - int next_state = STATE_START; - windows_inc_private *prp_priv = (windows_inc_private *)prp->private; - int done; - int e1; - RUV *ruv = NULL; - CSN *cons_schema_csn; - Replica *replica; - int wait_change_timer_set = 0; - time_t last_start_time; - PRUint32 num_changes_sent; - char *hostname = NULL; - int portnum = 0; - /* use a different backoff timer strategy for ACQUIRE_REPLICA_BUSY errors */ - PRBool use_busy_backoff_timer = PR_FALSE; - long pausetime = 0; - long busywaittime = 0; - - prp->stopped = 0; - prp->terminate = 0; - hostname = agmt_get_hostname(prp->agmt); - portnum = agmt_get_port(prp->agmt); - - /* establish_protocol_callbacks(prp); */ - done = 0; - do { - int rc; - - /* Take action, based on current state, and compute new state. */ - switch (current_state) - { - case STATE_START: - - dev_debug("windows_inc_run(STATE_START)"); - if (PROTOCOL_IS_SHUTDOWN(prp)) - { - done = 1; - break; - } + int current_state = STATE_START; + int next_state = STATE_START; + windows_inc_private *prp_priv = (windows_inc_private *)prp->private; + int done = 0; + int e1 = 0; + RUV *ruv = NULL; + Replica *replica = NULL; + int wait_change_timer_set = 0; + time_t last_start_time = 0; + PRUint32 num_changes_sent = 0; + char *hostname = NULL; + int portnum = 0; + /* use a different backoff timer strategy for ACQUIRE_REPLICA_BUSY errors */ + PRBool use_busy_backoff_timer = PR_FALSE; + long pausetime = 0; + long busywaittime = 0; + // Some operations should only be done the first time STATE_START is true. + static PRBool is_first_start = PR_TRUE; + + PRBool run_dirsync = PR_FALSE; + + LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_inc_run\n", 0, 0, 0 ); - /* - * Our initial state. See if we're in a schedule window. If - * so, then we're ready to acquire the replica and see if it - * needs any updates from us. If not, then wait for the window - * to open. - */ - if (agmt_schedule_in_window_now(prp->agmt)) - { - next_state = STATE_READY_TO_ACQUIRE; - } - else - { - next_state = STATE_WAIT_WINDOW_OPEN; - } + prp->stopped = 0; + prp->terminate = 0; + hostname = agmt_get_hostname(prp->agmt); + portnum = agmt_get_port(prp->agmt); - /* we can get here from other states because some events happened and were - not cleared. For instance when we wake up in STATE_WAIT_CHANGES state. - Since this is a fresh start state, we should clear all events */ - /* ONREPL - this does not feel right - we should take another look - at this state machine */ - reset_events (prp); - - /* Cancel any linger timer that might be in effect... */ - windows_conn_cancel_linger(prp->conn); - /* ... and disconnect, if currently connected */ - windows_conn_disconnect(prp->conn); - /* get the new pause time, if any */ - pausetime = agmt_get_pausetime(prp->agmt); - /* get the new busy wait time, if any */ - busywaittime = agmt_get_busywaittime(prp->agmt); - if (pausetime || busywaittime) - { - /* helper function to make sure they are set correctly */ - w_set_pause_and_busy_time(&pausetime, &busywaittime); - } - break; - case STATE_WAIT_WINDOW_OPEN: - /* - * We're waiting for a schedule window to open. If one did, - * or we receive a "replicate now" event, then start a protocol - * session immediately. If the replication schedule changed, go - * back to start. Otherwise, go back to sleep. - */ - dev_debug("windows_inc_run(STATE_WAIT_WINDOW_OPEN)"); - if (PROTOCOL_IS_SHUTDOWN(prp)) - { - done = 1; - break; - } - else if (event_occurred(prp, EVENT_WINDOW_OPENED)) - { - next_state = STATE_READY_TO_ACQUIRE; - } - else if (event_occurred(prp, EVENT_REPLICATE_NOW)) - { - next_state = STATE_READY_TO_ACQUIRE; - } - else if (event_occurred(prp, EVENT_AGMT_CHANGED)) - { - next_state = STATE_START; - windows_conn_set_agmt_changed(prp->conn); - } - else if (event_occurred(prp, EVENT_TRIGGERING_CRITERIA_MET)) /* change available */ - { - /* just ignore it and go to sleep */ - protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT); - } - else if (e1 = event_occurred(prp, EVENT_WINDOW_CLOSED) || - event_occurred(prp, EVENT_BACKOFF_EXPIRED)) - { - /* this events - should not occur - log a warning and go to sleep */ - slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, - "%s: Incremental protocol: " - "event %s should not occur in state %s; going to sleep\n", - agmt_get_long_name(prp->agmt), - e1 ? event2name(EVENT_WINDOW_CLOSED) : event2name(EVENT_BACKOFF_EXPIRED), - state2name(current_state)); - protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT); - } - else - { - /* wait until window opens or an event occurs */ - slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "%s: Incremental protocol: " - "waiting for update window to open\n", agmt_get_long_name(prp->agmt)); - protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT); - } - break; - case STATE_WAIT_CHANGES: - /* - * We're in a replication window, but we're waiting for more - * changes to accumulate before we actually hook up and send - * them. - */ - dev_debug("windows_inc_run(STATE_WAIT_CHANGES)"); - if (PROTOCOL_IS_SHUTDOWN(prp)) - { - dev_debug("windows_inc_run(STATE_WAIT_CHANGES): PROTOCOL_IS_SHUTING_DOWN -> end windows_inc_run\n"); - done = 1; - break; - } - else if (event_occurred(prp, EVENT_REPLICATE_NOW)) - { - dev_debug("windows_inc_run(STATE_WAIT_CHANGES): EVENT_REPLICATE_NOW received -> STATE_READY_TO_ACQUIRE\n"); - next_state = STATE_READY_TO_ACQUIRE; - wait_change_timer_set = 0; - } - else if (event_occurred(prp, EVENT_AGMT_CHANGED)) - { - dev_debug("windows_inc_run(STATE_WAIT_CHANGES): EVENT_AGMT_CHANGED received -> STATE_START\n"); - next_state = STATE_START; - windows_conn_set_agmt_changed(prp->conn); - wait_change_timer_set = 0; - } - else if (event_occurred(prp, EVENT_WINDOW_CLOSED)) - { - dev_debug("windows_inc_run(STATE_WAIT_CHANGES): EVENT_WINDOW_CLOSED received -> STATE_WAIT_WINDOW_OPEN\n"); - next_state = STATE_WAIT_WINDOW_OPEN; - wait_change_timer_set = 0; - } - else if (event_occurred(prp, EVENT_TRIGGERING_CRITERIA_MET)) - { - dev_debug("windows_inc_run(STATE_WAIT_CHANGES): EVENT_TRIGGERING_CRITERIA_MET received -> STATE_READY_TO_ACQUIRE\n"); - next_state = STATE_READY_TO_ACQUIRE; - wait_change_timer_set = 0; - } - else if (e1 = event_occurred(prp, EVENT_WINDOW_OPENED) || - event_occurred(prp, EVENT_BACKOFF_EXPIRED)) - { - /* this events - should not occur - log a warning and clear the event */ - slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "%s: Incremental protocol: " - "event %s should not occur in state %s\n", - agmt_get_long_name(prp->agmt), - e1 ? event2name(EVENT_WINDOW_OPENED) : event2name(EVENT_BACKOFF_EXPIRED), - state2name(current_state)); - wait_change_timer_set = 0; - } - else - { - if (wait_change_timer_set) - { - /* We are here because our timer expired */ - dev_debug("windows_inc_run(STATE_WAIT_CHANGES): wait_change_timer_set expired -> STATE_START\n"); - next_state = STATE_START; - wait_change_timer_set = 0; - } - else + windows_private_load_dirsync_cookie(prp->agmt); + + do { + int rc = 0; + + /* Take action, based on current state, and compute new state. */ + switch (current_state) { - /* We are here because the last replication session - * finished or aborted. - */ - wait_change_timer_set = 1; - protocol_sleep(prp, MAX_WAIT_BETWEEN_SESSIONS); - } - } - break; - case STATE_READY_TO_ACQUIRE: - - dev_debug("windows_inc_run(STATE_READY_TO_ACQUIRE)"); - if (PROTOCOL_IS_SHUTDOWN(prp)) - { - done = 1; - break; - } + case STATE_START: - /* ONREPL - at this state we unconditionally acquire the replica - ignoring all events. Not sure if this is good */ - object_acquire(prp->replica_object); - replica = object_get_data(prp->replica_object); - - rc = windows_acquire_replica(prp, &ruv); + dev_debug("windows_inc_run(STATE_START)"); + if (PROTOCOL_IS_SHUTDOWN(prp)) + { + done = 1; + break; + } - slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "windows_acquire_replica returned %s (%d)\n", - state2name(rc), - rc); + /* + * Our initial state. See if we're in a schedule window. If + * so, then we're ready to acquire the replica and see if it + * needs any updates from us. If not, then wait for the window + * to open. + */ + if (agmt_schedule_in_window_now(prp->agmt)) + { + next_state = STATE_READY_TO_ACQUIRE; + } else + { + next_state = STATE_WAIT_WINDOW_OPEN; + } - use_busy_backoff_timer = PR_FALSE; /* default */ - if (rc == ACQUIRE_SUCCESS) - { - next_state = STATE_SENDING_UPDATES; - } - else if (rc == ACQUIRE_REPLICA_BUSY) - { - next_state = STATE_BACKOFF_START; - use_busy_backoff_timer = PR_TRUE; - } - else if (rc == ACQUIRE_CONSUMER_WAS_UPTODATE) - { - next_state = STATE_WAIT_CHANGES; - } - else if (rc == ACQUIRE_TRANSIENT_ERROR) - { - next_state = STATE_BACKOFF_START; - } - else if (rc == ACQUIRE_FATAL_ERROR) - { - next_state = STATE_STOP_FATAL_ERROR; - } - if (rc != ACQUIRE_SUCCESS) - { - int optype, ldaprc; - windows_conn_get_error(prp->conn, &optype, &ldaprc); - agmt_set_last_update_status(prp->agmt, ldaprc, - prp->last_acquire_response_code, NULL); - } - - object_release(prp->replica_object); replica = NULL; - break; - case STATE_BACKOFF_START: - dev_debug("windows_inc_run(STATE_BACKOFF_START)"); - if (PROTOCOL_IS_SHUTDOWN(prp)) - { - done = 1; - break; - } - if (event_occurred(prp, EVENT_REPLICATE_NOW)) - { - next_state = STATE_READY_TO_ACQUIRE; - } - else if (event_occurred(prp, EVENT_AGMT_CHANGED)) - { - next_state = STATE_START; - windows_conn_set_agmt_changed(prp->conn); - } - else if (event_occurred (prp, EVENT_WINDOW_CLOSED)) - { - next_state = STATE_WAIT_WINDOW_OPEN; - } - else if (event_occurred (prp, EVENT_TRIGGERING_CRITERIA_MET)) - { - /* consume and ignore */ - } - else if (e1 = event_occurred (prp, EVENT_WINDOW_OPENED) || - event_occurred (prp, EVENT_BACKOFF_EXPIRED)) - { - /* This should never happen */ - /* this events - should not occur - log a warning and go to sleep */ - slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, - "%s: Incremental protocol: event %s should not occur in state %s\n", - agmt_get_long_name(prp->agmt), - e1 ? event2name(EVENT_WINDOW_OPENED) : event2name(EVENT_BACKOFF_EXPIRED), - state2name(current_state)); - } - else - { - /* Set up the backoff timer to wake us up at the appropriate time */ - if (use_busy_backoff_timer) - { - /* we received a busy signal from the consumer, wait for a while */ - if (!busywaittime) - { - busywaittime = PROTOCOL_BUSY_BACKOFF_MINIMUM; - } - prp_priv->backoff = backoff_new(BACKOFF_FIXED, busywaittime, - busywaittime); - } - else - { - prp_priv->backoff = backoff_new(BACKOFF_EXPONENTIAL, PROTOCOL_BACKOFF_MINIMUM, - PROTOCOL_BACKOFF_MAXIMUM); - } - next_state = STATE_BACKOFF; - backoff_reset(prp_priv->backoff, windows_inc_backoff_expired, (void *)prp); - protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT); - use_busy_backoff_timer = PR_FALSE; - } - break; - case STATE_BACKOFF: - /* - * We're in a backoff state. - */ - dev_debug("windows_inc_run(STATE_BACKOFF)"); - if (PROTOCOL_IS_SHUTDOWN(prp)) - { - if (prp_priv->backoff) - backoff_delete(&prp_priv->backoff); - done = 1; - break; - } - else if (event_occurred(prp, EVENT_REPLICATE_NOW)) - { - next_state = STATE_READY_TO_ACQUIRE; - } - else if (event_occurred(prp, EVENT_AGMT_CHANGED)) - { - next_state = STATE_START; + /* we can get here from other states because some events happened and were + not cleared. For instance when we wake up in STATE_WAIT_CHANGES state. + Since this is a fresh start state, we should clear all events */ + /* ONREPL - this does not feel right - we should take another look + at this state machine */ + reset_events (prp); + + /* Cancel any linger timer that might be in effect... */ + windows_conn_cancel_linger(prp->conn); + /* ... and disconnect, if currently connected */ + windows_conn_disconnect(prp->conn); + /* get the new pause time, if any */ + pausetime = agmt_get_pausetime(prp->agmt); + /* get the new busy wait time, if any */ + busywaittime = agmt_get_busywaittime(prp->agmt); + if (pausetime || busywaittime) + { + /* helper function to make sure they are set correctly */ + w_set_pause_and_busy_time(&pausetime, &busywaittime); + } - windows_conn_set_agmt_changed(prp->conn); - /* Destroy the backoff timer, since we won't need it anymore */ - if (prp_priv->backoff) - backoff_delete(&prp_priv->backoff); - } - else if (event_occurred(prp, EVENT_WINDOW_CLOSED)) - { - next_state = STATE_WAIT_WINDOW_OPEN; - /* Destroy the backoff timer, since we won't need it anymore */ - if (prp_priv->backoff) - backoff_delete(&prp_priv->backoff); - } - else if (event_occurred(prp, EVENT_BACKOFF_EXPIRED)) - { - rc = windows_acquire_replica(prp, &ruv); - use_busy_backoff_timer = PR_FALSE; - if (rc == ACQUIRE_SUCCESS) - { - next_state = STATE_SENDING_UPDATES; - } - else if (rc == ACQUIRE_REPLICA_BUSY) - { - next_state = STATE_BACKOFF; - use_busy_backoff_timer = PR_TRUE; - } - else if (rc == ACQUIRE_CONSUMER_WAS_UPTODATE) - { - next_state = STATE_WAIT_CHANGES; - } - else if (rc == ACQUIRE_TRANSIENT_ERROR) - { - next_state = STATE_BACKOFF; - } - else if (rc == ACQUIRE_FATAL_ERROR) - { - next_state = STATE_STOP_FATAL_ERROR; - } - if (rc != ACQUIRE_SUCCESS) - { - int optype, ldaprc; - windows_conn_get_error(prp->conn, &optype, &ldaprc); - agmt_set_last_update_status(prp->agmt, ldaprc, - prp->last_acquire_response_code, NULL); - } + + if (is_first_start) { + /* + * The function, the arguments, the time (hence) when it is first to be called, + * and the repeat interval. + */ + /* DBDB: we should probably make this polling interval configurable */ + dirsync = slapi_eq_repeat(periodic_dirsync, (void*) prp, (time_t)0 , PERIODIC_DIRSYNC_INTERVAL); + is_first_start = PR_FALSE; + } + break; + + case STATE_WAIT_WINDOW_OPEN: /* - * We either need to step the backoff timer, or - * destroy it if we don't need it anymore. + * We're waiting for a schedule window to open. If one did, + * or we receive a "replicate now" event, then start a protocol + * session immediately. If the replication schedule changed, go + * back to start. Otherwise, go back to sleep. */ - if (STATE_BACKOFF == next_state) - { - time_t next_fire_time; - time_t now; - /* Step the backoff timer */ - time(&now); - next_fire_time = backoff_step(prp_priv->backoff); - /* And go back to sleep */ - slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "%s: Replication session backing off for %d seconds\n", - agmt_get_long_name(prp->agmt), - next_fire_time - now); + dev_debug("windows_inc_run(STATE_WAIT_WINDOW_OPEN)"); + if (PROTOCOL_IS_SHUTDOWN(prp)) + { + done = 1; + break; + } + else if (event_occurred(prp, EVENT_WINDOW_OPENED)) + { + next_state = STATE_READY_TO_ACQUIRE; + } + else if (event_occurred(prp, EVENT_REPLICATE_NOW)) + { + next_state = STATE_READY_TO_ACQUIRE; + } + else if (event_occurred(prp, EVENT_AGMT_CHANGED)) + { + next_state = STATE_START; + run_dirsync = PR_TRUE; + windows_conn_set_agmt_changed(prp->conn); + } + else if (event_occurred(prp, EVENT_TRIGGERING_CRITERIA_MET)) /* change available */ + { + /* just ignore it and go to sleep */ + protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT); + } + else if (e1 = event_occurred(prp, EVENT_WINDOW_CLOSED) || + event_occurred(prp, EVENT_BACKOFF_EXPIRED)) + { + /* this events - should not occur - log a warning and go to sleep */ + slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, + "%s: Incremental protocol: " + "event %s should not occur in state %s; going to sleep\n", + agmt_get_long_name(prp->agmt), + e1 ? event2name(EVENT_WINDOW_CLOSED) : event2name(EVENT_BACKOFF_EXPIRED), + state2name(current_state)); + protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT); + } + else + { + /* wait until window opens or an event occurs */ + slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, + "%s: Incremental protocol: " + "waiting for update window to open\n", agmt_get_long_name(prp->agmt)); + protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT); + } + break; - protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT); - } - else - { - /* Destroy the backoff timer, since we won't need it anymore */ - backoff_delete(&prp_priv->backoff); - } - use_busy_backoff_timer = PR_FALSE; - } - else if (event_occurred(prp, EVENT_TRIGGERING_CRITERIA_MET)) - { - /* changes are available */ - if ( prp_priv->backoff == NULL || backoff_expired (prp_priv->backoff, 60) ) - { - /* - * Have seen cases that the agmt stuck here forever since - * somehow the backoff timer was not in event queue anymore. - * If the backoff timer has expired more than 60 seconds, - * destroy it. - */ - if ( prp_priv->backoff ) - backoff_delete(&prp_priv->backoff); - next_state = STATE_READY_TO_ACQUIRE; - } - else - { - /* ignore changes and go to sleep */ - protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT); - } - } - else if (event_occurred(prp, EVENT_WINDOW_OPENED)) - { - /* this should never happen - log an error and go to sleep */ - slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "%s: Incremental protocol: " - "event %s should not occur in state %s; going to sleep\n", - agmt_get_long_name(prp->agmt), - event2name(EVENT_WINDOW_OPENED), state2name(current_state)); - protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT); - } - break; + case STATE_WAIT_CHANGES: + /* + * We're in a replication window, but we're waiting for more + * changes to accumulate before we actually hook up and send + * them. + */ + dev_debug("windows_inc_run(STATE_WAIT_CHANGES)"); + if (PROTOCOL_IS_SHUTDOWN(prp)) + { + dev_debug("windows_inc_run(STATE_WAIT_CHANGES): PROTOCOL_IS_SHUTING_DOWN -> end windows_inc_run\n"); + done = 1; + break; + } + else if (event_occurred(prp, EVENT_REPLICATE_NOW)) + { + dev_debug("windows_inc_run(STATE_WAIT_CHANGES): EVENT_REPLICATE_NOW received -> STATE_READY_TO_ACQUIRE\n"); + next_state = STATE_READY_TO_ACQUIRE; + wait_change_timer_set = 0; + /* We also want to run dirsync on a 'replicate now' event */ + run_dirsync = PR_TRUE; + } + else if ( event_occurred(prp, EVENT_RUN_DIRSYNC)) + { + dev_debug("windows_inc_run(STATE_WAIT_CHANGES): EVENT_REPLICATE_NOW received -> STATE_READY_TO_ACQUIRE\n"); + next_state = STATE_READY_TO_ACQUIRE; + wait_change_timer_set = 0; + run_dirsync = PR_TRUE; + + } + else if (event_occurred(prp, EVENT_AGMT_CHANGED)) + { + dev_debug("windows_inc_run(STATE_WAIT_CHANGES): EVENT_AGMT_CHANGED received -> STATE_START\n"); + next_state = STATE_START; + windows_conn_set_agmt_changed(prp->conn); + wait_change_timer_set = 0; + /* We also want to run dirsync on a 'agreement changed' event, because that's how we receive 'send updates now' */ + run_dirsync = PR_TRUE; + } + else if (event_occurred(prp, EVENT_WINDOW_CLOSED)) + { + dev_debug("windows_inc_run(STATE_WAIT_CHANGES): EVENT_WINDOW_CLOSED received -> STATE_WAIT_WINDOW_OPEN\n"); + next_state = STATE_WAIT_WINDOW_OPEN; + wait_change_timer_set = 0; + } + else if (event_occurred(prp, EVENT_TRIGGERING_CRITERIA_MET) ) + { + dev_debug("windows_inc_run(STATE_WAIT_CHANGES): EVENT_TRIGGERING_CRITERIA_MET received -> STATE_READY_TO_ACQUIRE\n"); + next_state = STATE_READY_TO_ACQUIRE; + wait_change_timer_set = 0; + } + else if (e1 = event_occurred(prp, EVENT_WINDOW_OPENED) || + event_occurred(prp, EVENT_BACKOFF_EXPIRED)) + { + /* this events - should not occur - log a warning and clear the event */ + slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "%s: Incremental protocol: " + "event %s should not occur in state %s\n", + agmt_get_long_name(prp->agmt), + e1 ? event2name(EVENT_WINDOW_OPENED) : event2name(EVENT_BACKOFF_EXPIRED), + state2name(current_state)); + wait_change_timer_set = 0; + } + else + { + if (wait_change_timer_set) + { + /* We are here because our timer expired */ + dev_debug("windows_inc_run(STATE_WAIT_CHANGES): wait_change_timer_set expired -> STATE_START\n"); + next_state = STATE_START; + run_dirsync = PR_TRUE; + wait_change_timer_set = 0; + } + else + { + /* We are here because the last replication session + * finished or aborted. + */ + wait_change_timer_set = 1; + protocol_sleep(prp, MAX_WAIT_BETWEEN_SESSIONS); + } + } + break; + + case STATE_READY_TO_ACQUIRE: + + dev_debug("windows_inc_run(STATE_READY_TO_ACQUIRE)"); + if (PROTOCOL_IS_SHUTDOWN(prp)) + { + done = 1; + break; + } + + /* ONREPL - at this state we unconditionally acquire the replica + ignoring all events. Not sure if this is good */ + object_acquire(prp->replica_object); + replica = object_get_data(prp->replica_object); + + rc = windows_acquire_replica(prp, &ruv , 1 /* yes, check the consumer RUV for incremental */); + + slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, + "windows_acquire_replica returned %s (%d)\n", + acquire2name(rc), + rc); + + use_busy_backoff_timer = PR_FALSE; /* default */ + if (rc == ACQUIRE_SUCCESS) + { + next_state = STATE_SENDING_UPDATES; + } + else if (rc == ACQUIRE_REPLICA_BUSY) + { + next_state = STATE_BACKOFF_START; + use_busy_backoff_timer = PR_TRUE; + } + else if (rc == ACQUIRE_CONSUMER_WAS_UPTODATE) + { + next_state = STATE_WAIT_CHANGES; + + } + else if (rc == ACQUIRE_TRANSIENT_ERROR) + { + next_state = STATE_BACKOFF_START; + } + else if (rc == ACQUIRE_FATAL_ERROR) + { + next_state = STATE_STOP_FATAL_ERROR; + } + if (rc != ACQUIRE_SUCCESS) + { + int optype, ldaprc; + windows_conn_get_error(prp->conn, &optype, &ldaprc); + agmt_set_last_update_status(prp->agmt, ldaprc, + prp->last_acquire_response_code, NULL); + } + + object_release(prp->replica_object); replica = NULL; + break; + + case STATE_BACKOFF_START: + dev_debug("windows_inc_run(STATE_BACKOFF_START)"); + if (PROTOCOL_IS_SHUTDOWN(prp)) + { + done = 1; + break; + } + if (event_occurred(prp, EVENT_REPLICATE_NOW) || event_occurred(prp, EVENT_RUN_DIRSYNC)) + { + next_state = STATE_READY_TO_ACQUIRE; + } + else if (event_occurred(prp, EVENT_AGMT_CHANGED)) + { + next_state = STATE_START; + run_dirsync = PR_TRUE; /* Also trigger dirsync for the 'send updates now' feature */ + windows_conn_set_agmt_changed(prp->conn); + } + else if (event_occurred (prp, EVENT_WINDOW_CLOSED)) + { + next_state = STATE_WAIT_WINDOW_OPEN; + } + else if (event_occurred (prp, EVENT_TRIGGERING_CRITERIA_MET)) + { + /* consume and ignore */ + } + else if (e1 = event_occurred (prp, EVENT_WINDOW_OPENED) || + event_occurred (prp, EVENT_BACKOFF_EXPIRED)) + { + /* This should never happen */ + /* this events - should not occur - log a warning and go to sleep */ + slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, + "%s: Incremental protocol: event %s should not occur in state %s\n", + agmt_get_long_name(prp->agmt), + e1 ? event2name(EVENT_WINDOW_OPENED) : event2name(EVENT_BACKOFF_EXPIRED), + state2name(current_state)); + } + else + { + /* Set up the backoff timer to wake us up at the appropriate time */ + if (use_busy_backoff_timer) + { + /* we received a busy signal from the consumer, wait for a while */ + if (!busywaittime) + { + busywaittime = PROTOCOL_BUSY_BACKOFF_MINIMUM; + } + prp_priv->backoff = backoff_new(BACKOFF_FIXED, busywaittime, + busywaittime); + } + else + { + prp_priv->backoff = backoff_new(BACKOFF_EXPONENTIAL, PROTOCOL_BACKOFF_MINIMUM, + PROTOCOL_BACKOFF_MAXIMUM); + } + next_state = STATE_BACKOFF; + backoff_reset(prp_priv->backoff, windows_inc_backoff_expired, (void *)prp); + protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT); + use_busy_backoff_timer = PR_FALSE; + } + break; + + case STATE_BACKOFF: + /* + * We're in a backoff state. + */ + dev_debug("windows_inc_run(STATE_BACKOFF)"); + if (PROTOCOL_IS_SHUTDOWN(prp)) + { + if (prp_priv->backoff) + backoff_delete(&prp_priv->backoff); + done = 1; + break; + } + else if (event_occurred(prp, EVENT_REPLICATE_NOW) || event_occurred(prp, EVENT_RUN_DIRSYNC)) + { + next_state = STATE_READY_TO_ACQUIRE; + } + else if (event_occurred(prp, EVENT_AGMT_CHANGED)) + { + next_state = STATE_START; + run_dirsync = PR_TRUE; + + windows_conn_set_agmt_changed(prp->conn); + /* Destroy the backoff timer, since we won't need it anymore */ + if (prp_priv->backoff) + backoff_delete(&prp_priv->backoff); + } + else if (event_occurred(prp, EVENT_WINDOW_CLOSED)) + { + next_state = STATE_WAIT_WINDOW_OPEN; + /* Destroy the backoff timer, since we won't need it anymore */ + if (prp_priv->backoff) + backoff_delete(&prp_priv->backoff); + } + else if (event_occurred(prp, EVENT_BACKOFF_EXPIRED)) + { + rc = windows_acquire_replica(prp, &ruv, 1 /* check RUV for incremental */); + use_busy_backoff_timer = PR_FALSE; + if (rc == ACQUIRE_SUCCESS) + { + next_state = STATE_SENDING_UPDATES; + } + else if (rc == ACQUIRE_REPLICA_BUSY) + { + next_state = STATE_BACKOFF; + use_busy_backoff_timer = PR_TRUE; + } + else if (rc == ACQUIRE_CONSUMER_WAS_UPTODATE) + { + next_state = STATE_WAIT_CHANGES; + } + else if (rc == ACQUIRE_TRANSIENT_ERROR) + { + next_state = STATE_BACKOFF; + } + else if (rc == ACQUIRE_FATAL_ERROR) + { + next_state = STATE_STOP_FATAL_ERROR; + } + if (rc != ACQUIRE_SUCCESS) + { + int optype, ldaprc; + windows_conn_get_error(prp->conn, &optype, &ldaprc); + agmt_set_last_update_status(prp->agmt, ldaprc, + prp->last_acquire_response_code, NULL); + } + /* + * We either need to step the backoff timer, or + * destroy it if we don't need it anymore. + */ + if (STATE_BACKOFF == next_state) + { + time_t next_fire_time; + time_t now; + /* Step the backoff timer */ + time(&now); + next_fire_time = backoff_step(prp_priv->backoff); + /* And go back to sleep */ + slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, + "%s: Replication session backing off for %d seconds\n", + agmt_get_long_name(prp->agmt), + next_fire_time - now); + + protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT); + } + else + { + /* Destroy the backoff timer, since we won't need it anymore */ + backoff_delete(&prp_priv->backoff); + } + use_busy_backoff_timer = PR_FALSE; + } + else if (event_occurred(prp, EVENT_TRIGGERING_CRITERIA_MET)) + { + /* changes are available */ + if ( prp_priv->backoff == NULL || backoff_expired (prp_priv->backoff, 60) ) + { + /* + * Have seen cases that the agmt stuck here forever since + * somehow the backoff timer was not in event queue anymore. + * If the backoff timer has expired more than 60 seconds, + * destroy it. + */ + if ( prp_priv->backoff ) + backoff_delete(&prp_priv->backoff); + next_state = STATE_READY_TO_ACQUIRE; + } + else + { + /* ignore changes and go to sleep */ + protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT); + } + } + else if (event_occurred(prp, EVENT_WINDOW_OPENED)) + { + /* this should never happen - log an error and go to sleep */ + slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "%s: Incremental protocol: " + "event %s should not occur in state %s; going to sleep\n", + agmt_get_long_name(prp->agmt), + event2name(EVENT_WINDOW_OPENED), state2name(current_state)); + protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT); + } + break; case STATE_SENDING_UPDATES: dev_debug("windows_inc_run(STATE_SENDING_UPDATES)"); agmt_set_update_in_progress(prp->agmt, PR_TRUE); @@ -724,29 +720,6 @@ windows_inc_run(Private_Repl_Protocol *prp) agmt_set_last_update_status(prp->agmt, 0, 0, "Incremental update started"); - /* ONREPL - in this state we send changes no matter what other events occur. - This is because we can get because of the REPLICATE_NOW event which - has high priority. Is this ok? */ - /* First, push new schema to the consumer if needed */ - /* ONREPL - should we push schema after we examine the RUV? */ - /* - * GGOOREPL - I don't see why we should wait until we've - * examined the RUV. The schema entry has its own CSN that is - * used to decide if the remote schema needs to be updated. - */ - cons_schema_csn = agmt_get_consumer_schema_csn ( prp->agmt ); - // rc = windows_conn_push_schema(prp->conn, &cons_schema_csn); XXX - if ( cons_schema_csn != agmt_get_consumer_schema_csn ( prp->agmt )) - { - agmt_set_consumer_schema_csn ( prp->agmt, cons_schema_csn ); - } - if (CONN_SCHEMA_UPDATED != rc && CONN_SCHEMA_NO_UPDATE_NEEDED != rc) - { - slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, - "%s: Warning: unable to replicate schema: rc=%d\n", - agmt_get_long_name(prp->agmt), rc); - /* But keep going */ - } dev_debug("windows_inc_run(STATE_SENDING_UPDATES) -> windows_examine_update_vector"); rc = windows_examine_update_vector(prp, ruv); /* @@ -842,10 +815,14 @@ windows_inc_run(Private_Repl_Protocol *prp) last_start_time = 0UL; break; } -/* if (NULL != ruv) - { - ruv_destroy(&ruv); ruv = NULL; - } XXX elliot commented this out */ + + if ( run_dirsync ) + { + windows_dirsync_inc_run(prp); + windows_private_save_dirsync_cookie(prp->agmt); + run_dirsync = PR_FALSE; + } + agmt_set_last_update_end(prp->agmt, current_time()); agmt_set_update_in_progress(prp->agmt, PR_FALSE); /* If timed out, close the connection after released the replica */ @@ -882,7 +859,6 @@ windows_inc_run(Private_Repl_Protocol *prp) /* DS_Sleep ( PR_SecondsToInterval(1) ); */ } } - windows_dirsync_inc_run(prp); break; case STATE_STOP_FATAL_ERROR: @@ -960,6 +936,7 @@ windows_inc_run(Private_Repl_Protocol *prp) conn_cancel_linger(prp->conn); /* ... and disconnect, if currently connected */ conn_disconnect(prp->conn); + LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_inc_run\n", 0, 0, 0 ); } @@ -970,6 +947,7 @@ windows_inc_run(Private_Repl_Protocol *prp) static void protocol_sleep(Private_Repl_Protocol *prp, PRIntervalTime duration) { + LDAPDebug( LDAP_DEBUG_TRACE, "=> protocol_sleep\n", 0, 0, 0 ); PR_ASSERT(NULL != prp); PR_Lock(prp->lock); /* we should not go to sleep if there are events available to be processed. @@ -983,6 +961,7 @@ protocol_sleep(Private_Repl_Protocol *prp, PRIntervalTime duration) agmt_get_long_name(prp->agmt), prp->eventbits); } PR_Unlock(prp->lock); + LDAPDebug( LDAP_DEBUG_TRACE, "<= protocol_sleep\n", 0, 0, 0 ); } @@ -995,11 +974,13 @@ protocol_sleep(Private_Repl_Protocol *prp, PRIntervalTime duration) static void event_notify(Private_Repl_Protocol *prp, PRUint32 event) { + LDAPDebug( LDAP_DEBUG_TRACE, "=> event_notify\n", 0, 0, 0 ); PR_ASSERT(NULL != prp); PR_Lock(prp->lock); prp->eventbits |= event; PR_NotifyCondVar(prp->cvar); PR_Unlock(prp->lock); + LDAPDebug( LDAP_DEBUG_TRACE, "<= event_notify\n", 0, 0, 0 ); } @@ -1011,187 +992,36 @@ static PRUint32 event_occurred(Private_Repl_Protocol *prp, PRUint32 event) { PRUint32 return_value; + + LDAPDebug( LDAP_DEBUG_TRACE, "=> event_occurred\n", 0, 0, 0 ); + PR_ASSERT(NULL != prp); PR_Lock(prp->lock); return_value = (prp->eventbits & event); prp->eventbits &= ~event; /* Clear event */ PR_Unlock(prp->lock); + LDAPDebug( LDAP_DEBUG_TRACE, "<= event_occurred\n", 0, 0, 0 ); return return_value; } static void reset_events (Private_Repl_Protocol *prp) { + LDAPDebug( LDAP_DEBUG_TRACE, "=> reset_events\n", 0, 0, 0 ); PR_ASSERT(NULL != prp); PR_Lock(prp->lock); prp->eventbits = 0; PR_Unlock(prp->lock); + LDAPDebug( LDAP_DEBUG_TRACE, "<= reset_events\n", 0, 0, 0 ); } -/* - * Replay the actual update to the consumer. Construct an appropriate LDAP - * operation, attach the baggage LDAPv3 control that contains the CSN, etc., - * and send the operation to the consumer. - */ -ConnResult -w_replay_update(Private_Repl_Protocol *prp, slapi_operation_parameters *op) -{ - ConnResult return_value; - LDAPControl *update_control = NULL; - char csn_str[CSN_STRSIZE]; /* For logging only */ - char *old_dn; - char *password = NULL; - - old_dn = slapi_ch_strdup(op->target_address.dn); - - csn_as_string(op->csn, PR_FALSE, csn_str); - - if ( windows_private_get_windows_replarea(prp->agmt) && windows_private_get_directory_replarea(prp->agmt) ) - { - Slapi_DN *sdn; - - sdn = slapi_sdn_new_dn_passin( op->target_address.dn ); - sdn = map_dn_user(sdn, REPLICA_TYPE_WINDOWS, windows_private_get_windows_replarea( prp->agmt) ); - - op->target_address.dn = slapi_ch_strdup(slapi_sdn_get_ndn(sdn)); - - } - - /* Construct the replication info control that accompanies the operation */ - if (SLAPI_OPERATION_ADD == op->operation_type) - { - - map_entry_user(&(op->p.p_add.target_entry), REPLICA_TYPE_WINDOWS, &password); - - - } - else if (SLAPI_OPERATION_MODRDN == op->operation_type) - { - /* op->p.p_modrdn.modrdn_newrdn needs to change from - uid=fbar to cn=fbar */ - - - } - else if (SLAPI_OPERATION_MODIFY == op->operation_type) - { - alter_mods(& op->p.p_modify.modify_mods, &password) ; - /* if the entry already exists, modify_mods will be null. - attempting to modifiy null will return LDAP_PARAM_ERROR. - The password still might be set. bail */ - if ( op->p.p_modify.modify_mods == NULL) - { - return_value = CONN_OPERATION_SUCCESS; - goto skipchange; - } - - } - - slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "%s: replay_update: Sending %s operation (dn=\"%s\" csn=%s)\n", - agmt_get_long_name(prp->agmt), - op2string(op->operation_type), op->target_address.dn, csn_str); - /* What type of operation is it? */ - switch (op->operation_type) - { - case SLAPI_OPERATION_ADD: - { - LDAPMod **entryattrs; - /* Convert entry to mods */ - (void)slapi_entry2mods (op->p.p_add.target_entry, - NULL /* &entrydn : We don't need it */, - &entryattrs); - if (NULL == entryattrs) - { - slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, - "%s: replay_update: Cannot convert entry to LDAPMods.\n", - agmt_get_long_name(prp->agmt)); - return_value = CONN_LOCAL_ERROR; - } - else - { - return_value = windows_conn_send_add(prp->conn, op->target_address.dn, - entryattrs, update_control, NULL /* returned controls */); - ldap_mods_free(entryattrs, 1); - } - break; - } - case SLAPI_OPERATION_MODIFY: - return_value = windows_conn_send_modify(prp->conn, op->target_address.dn, - op->p.p_modify.modify_mods, update_control, - NULL /* returned controls */); - break; - case SLAPI_OPERATION_DELETE: - return_value = windows_conn_send_delete(prp->conn, op->target_address.dn, - update_control, NULL /* returned controls */); - break; - case SLAPI_OPERATION_MODRDN: - /* XXXggood need to pass modrdn mods in update control! */ - return_value = windows_conn_send_rename(prp->conn, op->target_address.dn, - op->p.p_modrdn.modrdn_newrdn, - op->p.p_modrdn.modrdn_newsuperior_address.dn, - op->p.p_modrdn.modrdn_deloldrdn, - update_control, NULL /* returned controls */); - break; - default: - slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "%s: replay_update: Unknown " - "operation type %d found in changelog - skipping change.\n", - agmt_get_long_name(prp->agmt), op->operation_type); - } - -skipchange: - if (NULL != password) - { /* this entry had a password, handle it seperately */ - /* http://support.microsoft.com/?kbid=269190 */ - - int pw_return; - LDAPMod *pw_mods[2]; - LDAPMod pw_mod; - - char *pw[2]; - pw[0] = password; - pw[1] = NULL; - - pw_mod.mod_type = "UnicodePwd"; - pw_mod.mod_op = LDAP_MOD_REPLACE; - pw_mod.mod_values = pw; - - pw_mods[0] = &pw_mod; - pw_mods[1] = NULL; - - - pw_return = windows_conn_send_modify(prp->conn, op->target_address.dn, - pw_mods, NULL, NULL ); - slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "%s: replay_update: update password returned %d\n", - agmt_get_long_name(prp->agmt), pw_return ); - - - // slapi_ch_free((void**) &password); - - } - - /* XXX - what else should be 'ignored' here?. and in which cases? - Or should this go in a different part of the file? */ - if ( CONN_OPERATION_SUCCESS == return_value ) - { - slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "%s: replay_update: Consumer successfully replayed operation with csn %s\n", - agmt_get_long_name(prp->agmt), csn_str); - } - else - { - slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "%s: replay_update: Consumer could not replay operation with csn %s\n", - agmt_get_long_name(prp->agmt), csn_str); - } - return return_value; -} static PRBool is_dummy_operation (const slapi_operation_parameters *op) { + LDAPDebug( LDAP_DEBUG_TRACE, "=> is_dummy_operation\n", 0, 0, 0 ); + LDAPDebug( LDAP_DEBUG_TRACE, "<= is_dummy_operation\n", 0, 0, 0 ); return (strcmp (op->target_address.uniqueid, START_ITERATION_ENTRY_UNIQUEID) == 0); } @@ -1200,6 +1030,7 @@ is_dummy_operation (const slapi_operation_parameters *op) void w_cl5_operation_parameters_done (struct slapi_operation_parameters *sop) { + LDAPDebug( LDAP_DEBUG_TRACE, "=> w_cl5_operation_parameters_done\n", 0, 0, 0 ); if(sop!=NULL) { switch(sop->operation_type) { @@ -1234,7 +1065,7 @@ w_cl5_operation_parameters_done (struct slapi_operation_parameters *sop) } } operation_parameters_done(sop); - + LDAPDebug( LDAP_DEBUG_TRACE, "<= w_cl5_operation_parameters_done\n", 0, 0, 0 ); } @@ -1258,6 +1089,8 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu int rc; CL5ReplayIterator *changelog_iterator = NULL; + LDAPDebug( LDAP_DEBUG_TRACE, "=> send_updates\n", 0, 0, 0 ); + *num_changes_sent = 0; /* * Iterate over the changelog. Retrieve each update, @@ -1265,8 +1098,8 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu * attaching the CSN, and send the change. */ - //rc = cl5CreateReplayIterator( prp, remote_update_vector, &changelog_iterator); // XXX fixme - rc = cl5CreateReplayIteratorEx( prp, remote_update_vector, &changelog_iterator, agmt_get_consumerRID(prp->agmt)); // XXX fixme + + rc = cl5CreateReplayIteratorEx( prp, remote_update_vector, &changelog_iterator, agmt_get_consumerRID(prp->agmt)); if (CL5_SUCCESS != rc) { switch (rc) @@ -1388,7 +1221,8 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu agmt_get_long_name(prp->agmt), csn_as_string(entry.op->csn, PR_FALSE, csn_str)); continue; } - replay_crc = w_replay_update(prp, entry.op); + /* This is where the work actually happens: */ + replay_crc = windows_replay_update(prp, entry.op); if (CONN_OPERATION_SUCCESS != replay_crc) { int operation, error; @@ -1459,6 +1293,9 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu /* Positive response received */ (*num_changes_sent)++; agmt_inc_last_update_changecount (prp->agmt, csn_get_replicaid(entry.op->csn), 0 /*replayed*/); + + /* bring the consumers (AD) RUV up to date */ + /* DBDB removed because it breaks server startup ruv_set_max_csn(remote_update_vector,entry.op->csn, NULL ); */ } break; case CL5_BAD_DATA: @@ -1515,6 +1352,7 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu w_cl5_operation_parameters_done ( entry.op ); cl5DestroyReplayIterator(&changelog_iterator); } + LDAPDebug( LDAP_DEBUG_TRACE, "<= send_updates\n", 0, 0, 0 ); return return_value; } @@ -1531,6 +1369,8 @@ windows_inc_stop(Private_Repl_Protocol *prp) PRIntervalTime start, maxwait, now; int seconds = 1200; + LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_inc_stop\n", 0, 0, 0 ); + maxwait = PR_SecondsToInterval(seconds); prp->terminate = 1; event_notify(prp, EVENT_PROTOCOL_SHUTDOWN); @@ -1557,6 +1397,7 @@ windows_inc_stop(Private_Repl_Protocol *prp) agmt_get_long_name(prp->agmt), PR_IntervalToSeconds(now-start)); } + LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_inc_stop\n", 0, 0, 0 ); return return_value; } @@ -1567,6 +1408,10 @@ windows_inc_status(Private_Repl_Protocol *prp) { int return_value = 0; + LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_inc_status\n", 0, 0, 0 ); + + LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_inc_status\n", 0, 0, 0 ); + return return_value; } @@ -1575,40 +1420,54 @@ windows_inc_status(Private_Repl_Protocol *prp) static void windows_inc_notify_update(Private_Repl_Protocol *prp) { + LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_inc_notify_update\n", 0, 0, 0 ); event_notify(prp, EVENT_TRIGGERING_CRITERIA_MET); + LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_inc_notify_update\n", 0, 0, 0 ); } static void windows_inc_update_now(Private_Repl_Protocol *prp) { + LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_inc_update_now\n", 0, 0, 0 ); event_notify(prp, EVENT_REPLICATE_NOW); + LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_inc_update_now\n", 0, 0, 0 ); } static void windows_inc_notify_agmt_changed(Private_Repl_Protocol *prp) { + LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_inc_notify_agmt_changed\n", 0, 0, 0 ); event_notify(prp, EVENT_AGMT_CHANGED); + LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_inc_notify_agmt_changed\n", 0, 0, 0 ); } static void windows_inc_notify_window_opened (Private_Repl_Protocol *prp) { + LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_inc_notify_window_opened\n", 0, 0, 0 ); event_notify(prp, EVENT_WINDOW_OPENED); + LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_inc_notify_window_opened\n", 0, 0, 0 ); } static void windows_inc_notify_window_closed (Private_Repl_Protocol *prp) { + LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_inc_notify_window_closed\n", 0, 0, 0 ); event_notify(prp, EVENT_WINDOW_CLOSED); + LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_inc_notify_window_closed\n", 0, 0, 0 ); } + Private_Repl_Protocol * Windows_Inc_Protocol_new(Repl_Protocol *rp) { windows_inc_private *rip = NULL; Private_Repl_Protocol *prp = (Private_Repl_Protocol *)slapi_ch_malloc(sizeof(Private_Repl_Protocol)); + + LDAPDebug( LDAP_DEBUG_TRACE, "=> Windows_Inc_Protocol_new\n", 0, 0, 0 ); + prp->delete = windows_inc_delete; prp->run = windows_inc_run; prp->stop = windows_inc_stop; @@ -1639,9 +1498,14 @@ Windows_Inc_Protocol_new(Repl_Protocol *rp) rip->rp = rp; prp->private = (void *)rip; prp->replica_acquired = PR_FALSE; + + LDAPDebug( LDAP_DEBUG_TRACE, "<= Windows_Inc_Protocol_new\n", 0, 0, 0 ); + return prp; + loser: windows_inc_delete(&prp); + LDAPDebug( LDAP_DEBUG_TRACE, "<= Windows_Inc_Protocol_new (loser)\n", 0, 0, 0 ); return NULL; } @@ -1652,8 +1516,13 @@ static void windows_inc_backoff_expired(time_t timer_fire_time, void *arg) { Private_Repl_Protocol *prp = (Private_Repl_Protocol *)arg; + + LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_inc_backoff_expired\n", 0, 0, 0 ); + PR_ASSERT(NULL != prp); event_notify(prp, EVENT_BACKOFF_EXPIRED); + + LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_inc_backoff_expired\n", 0, 0, 0 ); } @@ -1679,6 +1548,8 @@ windows_examine_update_vector(Private_Repl_Protocol *prp, RUV *remote_ruv) { int return_value; + LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_examine_update_vector\n", 0, 0, 0 ); + PR_ASSERT(NULL != prp); if (NULL == prp) { @@ -1718,6 +1589,7 @@ windows_examine_update_vector(Private_Repl_Protocol *prp, RUV *remote_ruv) slapi_ch_free((void**)&remote_gen); slapi_ch_free((void**)&local_gen); } + LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_examine_update_vector\n", 0, 0, 0 ); return return_value; } @@ -1742,6 +1614,8 @@ ignore_error_and_keep_going(int error) { int return_value; + LDAPDebug( LDAP_DEBUG_TRACE, "=> ignore_error_and_keep_going\n", 0, 0, 0 ); + switch (error) { /* Cases where we keep going */ @@ -1811,13 +1685,32 @@ ignore_error_and_keep_going(int error) return_value = PR_FALSE; break; } + LDAPDebug( LDAP_DEBUG_TRACE, "<= ignore_error_and_keep_going\n", 0, 0, 0 ); return return_value; } +/* this function converts an aquisition code to a string - for debug output */ +static const char* +acquire2name (int code) +{ + switch (code) + { + case ACQUIRE_SUCCESS: return "success"; + case ACQUIRE_REPLICA_BUSY: return "replica_busy"; + case ACQUIRE_FATAL_ERROR: return "fatal_error"; + case ACQUIRE_CONSUMER_WAS_UPTODATE: return "consumer_was_uptodate"; + case ACQUIRE_TRANSIENT_ERROR: return "transient_error"; + default: return "invalid_code"; + } +} + + /* this function converts a state to its name - for debug output */ static const char* state2name (int state) { + LDAPDebug( LDAP_DEBUG_TRACE, "=> state2name\n", 0, 0, 0 ); + LDAPDebug( LDAP_DEBUG_TRACE, "<= state2name\n", 0, 0, 0 ); switch (state) { case STATE_START: return "start"; @@ -1838,6 +1731,8 @@ state2name (int state) static const char* event2name (int event) { + LDAPDebug( LDAP_DEBUG_TRACE, "=> event2name\n", 0, 0, 0 ); + LDAPDebug( LDAP_DEBUG_TRACE, "<= event2name\n", 0, 0, 0 ); switch (event) { case EVENT_WINDOW_OPENED: return "update_window_opened"; @@ -1847,763 +1742,20 @@ event2name (int event) case EVENT_REPLICATE_NOW: return "replicate_now"; case EVENT_PROTOCOL_SHUTDOWN: return "protocol_shutdown"; case EVENT_AGMT_CHANGED: return "agreement_changed"; + case EVENT_RUN_DIRSYNC: return "run_dirsync"; default: return "invalid_event"; } } -static const char* -op2string(int op) -{ - switch (op) { - case SLAPI_OPERATION_ADD: - return "add"; - case SLAPI_OPERATION_MODIFY: - return "modify"; - case SLAPI_OPERATION_DELETE: - return "delete"; - case SLAPI_OPERATION_MODRDN: - return "rename"; - case SLAPI_OPERATION_EXTENDED: - return "extended"; - } - - return "unknown"; -} - - - -void map_entry_user(Slapi_Entry **e, int map_to, char** password) { - /* do schema changes */ - - Slapi_Entry *new_entry; - Slapi_Attr *a; - Slapi_Attr **attr = &a; - Slapi_Attr *prevattr = NULL; - int rc; - char* ldif = ""; /* for debugging only */ - int ldif_len=0; /* for debugging only */ - - a = slapi_attr_new(); - - new_entry = slapi_entry_alloc(); - - - rc =slapi_entry_first_attr( *e, attr ); - - while (rc == 0) - { - char* attr_type; - Slapi_Value *old_value; - int i=-1; - int ret = 0; - slapi_attr_get_type(*attr, &attr_type); - - - while ( mapping[++i].old_name != NULL) - { - - - if ((mapping[i].map_to == map_to) && strcasecmp(attr_type, mapping[i].old_name) == 0 ) - { - - slapi_attr_first_value( *attr, &old_value); - slapi_entry_add_value (new_entry, mapping[i].new_name, old_value); - - slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "translate_attrib \n\t%s\n\t%s\n", mapping[i].old_name, mapping[i].new_name); - - } - - } - - if ((map_to == REPLICA_TYPE_WINDOWS) && ( - slapi_attr_type_cmp(attr_type, PSEUDO_ATTR_UNHASHEDUSERPASSWORD , 1) == 0)) - { - int b; - const char* pw; - pw = slapi_value_get_string(old_value); - - *password = (char*) slapi_ch_malloc(strlen( pw ) + 3); /* "%s"\0 */ - b = sprintf(*password, "\"%s\"", pw); - - } - - - if (mapping[i].old_name != NULL) { - slapi_attr_first_value( *attr, &old_value); - ret = slapi_entry_add_value (new_entry, mapping[i].new_name, old_value); - } - - prevattr = *attr; - rc = slapi_entry_next_attr( *e, prevattr, attr ); - - } - /* replace the existing entry with our duplicate */ - { - char *ad_objectclass[] = {"top", "person", "organizationalperson", "user", NULL}; - char *ds_objectclass[] = {"top", "person", "organizationalperson", "inetorgperson", "ntuser", NULL}; - - Slapi_ValueSet *vs = slapi_valueset_new(); - Slapi_Value * addval; - int j = -1; - - if (map_to == REPLICA_TYPE_WINDOWS) { - - while (ad_objectclass[++j]!= NULL) - { - addval = slapi_value_new_string(ad_objectclass[j]); - slapi_valueset_add_value(vs,addval); - slapi_value_free(&addval); - } - } - else - { - while (ds_objectclass[++j]!= NULL) - { - addval = slapi_value_new_string(ds_objectclass[j]); - slapi_valueset_add_value(vs,addval); - slapi_value_free(&addval); - } - } - - slapi_entry_add_valueset(new_entry,"objectclass", vs); - slapi_valueset_free(vs); - - } - - /* - ldif = slapi_entry2str( *e, &ldif_len ); - slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "found entry %s from windows:\n%s\n", slapi_entry_get_ndn(*e), ldif); - ldif = slapi_entry2str( new_entry, &ldif_len ); - slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "found entry %s from windows:\n%s\n", slapi_entry_get_ndn(new_entry), ldif); - slapi_ch_free_string(&ldif); -*/ - - - *e = slapi_entry_dup( new_entry ); - -} - - -void map_entry_group(Slapi_Entry **e, int map_to) { - /* do schema changes */ - - Slapi_Entry *new_entry; - Slapi_Attr *a; - Slapi_Attr **attr = &a; - Slapi_Attr *prevattr = NULL; - int rc; - char* ldif = ""; /* for debugging only */ - int ldif_len=0; /* for debugging only */ - - a = slapi_attr_new(); - - new_entry = slapi_entry_alloc(); - - - rc =slapi_entry_first_attr( *e, attr ); - - while (rc == 0) - { - char* attr_type; - Slapi_Value *old_value; - int i=-1; - int ret = 0; - slapi_attr_get_type(*attr, &attr_type); - - - while ( group_map[++i].old_name != NULL) - { - - - if ((group_map[i].map_to == map_to) && strcasecmp(attr_type, group_map[i].old_name) == 0 ) - { - - slapi_attr_first_value( *attr, &old_value); - slapi_entry_add_value (new_entry, group_map[i].new_name, old_value); - - slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "translate_attrib \n\t%s\n\t%s\n", group_map[i].old_name, group_map[i].new_name); - - } - - } - - if (group_map[i].old_name != NULL) { - slapi_attr_first_value( *attr, &old_value); - ret = slapi_entry_add_value (new_entry, group_map[i].new_name, old_value); - } - - prevattr = *attr; - rc = slapi_entry_next_attr( *e, prevattr, attr ); - - } - /* replace the existing entry with our duplicate */ - { - char *ad_objectclass[] = {"top", "group", NULL}; - char *ds_objectclass[] = {"top", "ntGroup", NULL}; - - Slapi_ValueSet *vs = slapi_valueset_new(); - Slapi_Value * addval; - int j = -1; - - if (map_to == REPLICA_TYPE_WINDOWS) { - - while (ad_objectclass[++j]!= NULL) - { - addval = slapi_value_new_string(ad_objectclass[j]); - slapi_valueset_add_value(vs,addval); - slapi_value_free(&addval); - } - } - else - { - while (ds_objectclass[++j]!= NULL) - { - addval = slapi_value_new_string(ds_objectclass[j]); - slapi_valueset_add_value(vs,addval); - slapi_value_free(&addval); - } - } - - slapi_entry_add_valueset(new_entry,"objectclass", vs); - slapi_valueset_free(vs); - - } - - - ldif = slapi_entry2str( *e, &ldif_len ); - slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "found entry %s from windows:\n%s\n", slapi_entry_get_ndn(*e), ldif); - ldif = slapi_entry2str( new_entry, &ldif_len ); - slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "found entry %s from windows:\n%s\n", slapi_entry_get_ndn(new_entry), ldif); - slapi_ch_free_string(&ldif); - - - - *e = slapi_entry_dup( new_entry ); - -} - -static Slapi_DN* map_dn_user(Slapi_DN *sdn, int map_to, const Slapi_DN *root) -{ - /* function operation - convert to rdn - pop off naming attribute of sdn "{ cn | uid }" - replace with other naming attribute "{ uid | cn }" - append root - return sdn by reference - */ - Slapi_RDN *old_rdn = NULL; - Slapi_RDN *new_rdn = NULL; - char* naming_type = ""; - char* naming_value= ""; - Slapi_DN *return_sdn = NULL; - int rc = 0; - char* tempdn; - - PR_ASSERT(sdn); - PR_ASSERT(root); - - old_rdn = slapi_rdn_new_sdn(sdn); /* cn=administrator */ - - new_rdn = slapi_rdn_new(); - - rc = slapi_rdn_get_first(old_rdn, &naming_type, &naming_value); /* cn administrator */ - - if (map_to == REPLICA_TYPE_MULTIMASTER) - naming_type = slapi_ch_strdup("uid"); /* uid administrator */ - else if (map_to == REPLICA_TYPE_WINDOWS) - naming_type = slapi_ch_strdup("cn"); - - - rc = slapi_rdn_add(new_rdn, naming_type, naming_value); /* uid=administrator */ - - /* XXX this should be done with SDN and not char* */ - - tempdn = (char*) slapi_ch_malloc( strlen (naming_type) + strlen(naming_value) + - slapi_sdn_get_ndn_len(root) + 4); - - sprintf(tempdn, "%s=%s, %s", naming_type, naming_value, slapi_sdn_get_ndn(root) ); - - - return_sdn = slapi_sdn_new_dn_byref(tempdn); - - - return return_sdn; - -} - -static Slapi_DN* map_dn_group(Slapi_DN *sdn, int map_to, const Slapi_DN *root) -{ - /* function operation - convert to rdn - append root - return sdn by reference - */ - Slapi_RDN *old_rdn = NULL; - Slapi_RDN *new_rdn = NULL; - char* naming_type = ""; - char* naming_value= ""; - Slapi_DN *return_sdn = NULL; - int rc = 0; - char* tempdn; - - PR_ASSERT(sdn); - PR_ASSERT(root); - - old_rdn = slapi_rdn_new_sdn(sdn); /* cn=administrator */ - - new_rdn = slapi_rdn_new(); - - rc = slapi_rdn_get_first(old_rdn, &naming_type, &naming_value); /* cn administrator */ - - rc = slapi_rdn_add(new_rdn, naming_type, naming_value); - - /* XXX this should be done with SDN and not char* */ - - tempdn = (char*) slapi_ch_malloc( strlen (naming_type) + strlen(naming_value) + - slapi_sdn_get_ndn_len(root) + 4); - - sprintf(tempdn, "%s=%s, %s", naming_type, naming_value, slapi_sdn_get_ndn(root) ); - - - return_sdn = slapi_sdn_new_dn_passin(tempdn); - - - return return_sdn; - -} - -static void alter_mods(LDAPMod ***m, char** password) +static void +periodic_dirsync(time_t when, void *arg) { - LDAPMod **mods = *m; - int i=0; - - while (NULL != mods && NULL != mods[i]) - { - int j=-1; /* index of the attribute mapping array */ - char* attr_type; - attr_type = slapi_ch_strdup(mods[i]->mod_type); - while ( mapping[++j].old_name != NULL) - { - - if ( (mapping[j].map_to == REPLICA_TYPE_WINDOWS) && - (slapi_attr_type_cmp(attr_type, mapping[j].old_name, 1) == 0 ) ) - { - mods[i]->mod_type = slapi_ch_strdup(mapping[j].new_name); - - slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "alter_mods \n\t%s\n\t%s\n", mapping[j].old_name, mapping[j].new_name); - break; - - } - } - - if (slapi_attr_type_cmp(attr_type, PSEUDO_ATTR_UNHASHEDUSERPASSWORD , 1) == 0) - { - int b; - char *pw; - if (mods[i]->mod_op | LDAP_MOD_BVALUES) - { - *password = (char*) slapi_ch_malloc(strlen( mods[i]->mod_bvalues[0]->bv_val) + 3); /* "%s"\0 */ - pw = mods[i]->mod_bvalues[0]->bv_val; - } - else - { - *password = (char*) slapi_ch_malloc(strlen( mods[i]->mod_values[0]) + 3); /* "%s"\0 */ - pw = mods[i]->mod_values[0]; - } - - b = sprintf(*password, "\"%s\"", pw); - - - } - - if (mapping[j].old_name == NULL) - { - LDAPMod *this_mod = mods[i]; - - /* Move down all subsequent mods */ - int k = 0; - for (k = i; mods[k+1] ; k++) - { - mods[k] = mods[k+1]; - } - /* Zero the end of the array */ - mods[k] = NULL; - /* Adjust value of j, implicit in not incrementing it */ - /* Free this mod */ - ber_bvecfree(this_mod->mod_bvalues); - slapi_ch_free((void **)&(this_mod->mod_type)); - slapi_ch_free((void **)&this_mod); - } - else - i++; - } -} - - -/* the entry has already been translated, so be sure to search for ntuserid - and not samaccountname or anything else. */ - -static Slapi_Entry* windows_entry_already_exists(Slapi_Entry *e){ - - int rc = 0; - Slapi_DN *sdn = NULL; - Slapi_Entry *entry = NULL; - - sdn = slapi_entry_get_sdn(e); - rc = slapi_search_internal_get_entry( sdn, NULL, &entry, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION)); - - if (rc == LDAP_SUCCESS) - { - return entry; - } - else - { - return NULL; - } - -} - -static PRBool entry_is_tombstone(Slapi_Entry *e){ - return PR_FALSE; -} - -static int delete_user(Slapi_Entry *e){ - const char* dn; - const char* new_dn; - Slapi_PBlock *pb = NULL; - Slapi_DN *sdn = NULL; - int return_value = 0; - - PR_ASSERT(e); - - dn = slapi_ch_strdup( slapi_entry_get_ndn(e) ); - new_dn = slapi_ch_strdup(dn); - - /* XXX dn parsing in this if block could use some improvement */ - if ( strstr(new_dn, "\ndel:") != NULL ) - { - char* comma; - const char* c = ","; - pb = slapi_pblock_new(); - - comma = strstr(dn, c); - - strcpy( strstr(new_dn, "\ndel:"), comma); - - slapi_delete_internal_set_pb(pb, new_dn, NULL, NULL, repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0); - slapi_delete_internal_pb(pb); - - slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &return_value); - slapi_pblock_destroy(pb); - - - } - else - { - return_value = -1; - } - - slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "delete operation of entry %s returned: %d\n", new_dn, return_value); - - slapi_ch_free((void**) &dn); - slapi_ch_free((void**) &new_dn); - - return return_value; -} - - -static void make_mods_from_entries(Slapi_Entry *new_entry, Slapi_Entry *existing_entry, LDAPMod ***attrs){ - Slapi_Attr *attr; - int rc = 0; - Slapi_Mods smods; - - PR_ASSERT (new_entry && attrs && existing_entry); - - slapi_mods_init (&smods, 0); - - rc =slapi_entry_first_attr( new_entry, &attr ); - - while (rc == 0) - { - char* attr_type; - Slapi_Attr *existing_attr; - int i=-1; - Slapi_Value *v1 = NULL; - Slapi_Value *v2 = NULL; - - slapi_attr_get_type(attr, &attr_type); - - slapi_attr_first_value( attr, &v1); - - if (slapi_entry_attr_find(existing_entry, attr_type, &existing_attr) == 0) - { - /* found */ - slapi_attr_first_value( existing_attr, &v2); - - if (slapi_value_compare(existing_attr, v1, v2) == 0) - { - /* same, do nothing */ - /* slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "make_mods_from_entries: %s has same value (%s) on both sides\n", attr_type, slapi_value_get_string(v1)); */ - - } - else - { - /* attributes different -- create CHANGE */ - /* slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "make_mods_from_entries: %s has different value (%s, %s)\n", - attr_type, slapi_value_get_string(v1),slapi_value_get_string(v2)); */ - - slapi_mods_add_mod_values(&smods, LDAP_MOD_REPLACE, attr_type, &v1 ); - } - - - } - else - { - /* not found -- create ADD */ - /*slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "make_mods_from_entries: %s has no value ( will be %s)\n", - attr_type, slapi_value_get_string(v1)); */ - - - slapi_mods_add_mod_values(&smods, LDAP_MOD_ADD, attr_type, &v1 ); - - } - - /* XXX TODO: - delete an attribute */ - - rc = slapi_entry_next_attr(new_entry, attr, &attr); - - - } - *attrs = slapi_mods_get_ldapmods_passout (&smods); - slapi_mods_done (&smods); - - -} - -int add_or_modify_user(Slapi_Entry *e){ - Slapi_PBlock *pb = NULL; - int return_value = 0; - char *dn; - Slapi_Entry *existing = NULL; - - pb = slapi_pblock_new(); - dn = slapi_ch_strdup( slapi_entry_get_ndn(e) ); - - existing = windows_entry_already_exists(e); - if ( existing == NULL) - { - slapi_add_entry_internal_set_pb(pb, e, NULL, - repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), - 0); - slapi_add_internal_pb(pb); - - } - else - { - LDAPMod **mods; - make_mods_from_entries(e, existing, &mods); - if (NULL == mods) - { /* also get null if there are no differences, so this is ok. */ - slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, - "add_or_modify_user: Cannot convert entry %s to LDAPMods.\n", dn ); - return_value = 0; - goto bail; - } - - slapi_modify_internal_set_pb (pb, slapi_entry_get_ndn(e), mods, NULL, NULL, - repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0); - slapi_modify_internal_pb (pb); - ldap_mods_free(mods, 1); - } - - - - slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &return_value); + LDAPDebug( LDAP_DEBUG_TRACE, "=> periodic_dirsync\n", 0, 0, 0 ); slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "operation of entry %s returned: %d\n", dn, return_value); - -bail: - - if (pb) - slapi_pblock_destroy(pb); + "Running Dirsync \n"); - return return_value; + event_notify( (Private_Repl_Protocol*) arg, EVENT_RUN_DIRSYNC); + LDAPDebug( LDAP_DEBUG_TRACE, "<= periodic_dirsync\n", 0, 0, 0 ); } - - -int add_or_modify_group(Slapi_Entry *e){ - Slapi_PBlock *pb = NULL; - int return_value = 0; - char *dn; - Slapi_Entry *existing = NULL; - - pb = slapi_pblock_new(); - dn = slapi_ch_strdup( slapi_entry_get_ndn(e) ); - - existing = windows_entry_already_exists(e); - if ( existing == NULL) - { - slapi_add_entry_internal_set_pb(pb, e, NULL, - repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), - 0); - slapi_add_internal_pb(pb); - - } - else - { - LDAPMod **mods; - make_mods_from_entries(e, existing, &mods); - if (NULL == mods) - { /* also get null if there are no differences, so this is ok. */ - slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, - "add_or_modify_user: Cannot convert entry %s to LDAPMods.\n", dn ); - return_value = 0; - goto bail; - } - - slapi_modify_internal_set_pb (pb, slapi_entry_get_ndn(e), mods, NULL, NULL, - repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0); - slapi_modify_internal_pb (pb); - ldap_mods_free(mods, 1); - } - - - - slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &return_value); - - slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "operation of entry %s returned: %d\n", dn, return_value); - -bail: - - if (pb) - slapi_pblock_destroy(pb); - - return return_value; -} - - - -void windows_dirsync_inc_run(Private_Repl_Protocol *prp) - { - - int rc; - int msgid=0; - Slapi_PBlock *pb = NULL; - Slapi_Filter *filter_user = NULL; - Slapi_Filter *filter_user_deleted = NULL; - Slapi_Filter *filter_group = NULL; - Slapi_Filter *filter_group_deleted = NULL; - - rc = perform_search(prp->conn); - if (rc == CONN_OPERATION_SUCCESS) - { - - Slapi_Entry *e; - int filter_ret = 0; - - -#define FILTER_USER "(objectclass=user)" -#define FILTER_GROUP "(objectclass=group)" -#define FILTER_USER_DELETED "(&(isdeleted=*)(objectclass=user))" -#define FILTER_GROUP_DELETED "(&(isdeleted=*)(objectclass=group))" - - filter_user = slapi_str2filter( slapi_ch_strdup( FILTER_USER ) ); - filter_user_deleted = slapi_str2filter( slapi_ch_strdup( FILTER_USER_DELETED ) ); - filter_group = slapi_str2filter( slapi_ch_strdup( FILTER_GROUP ) ); - filter_group_deleted = slapi_str2filter( slapi_ch_strdup( FILTER_GROUP_DELETED ) ); - - - - while ((e = windows_conn_get_search_result(prp->conn)) != NULL) - { - const Slapi_DN* sdn = NULL; - /* deleted users are outside the 'correct container'. - They live in cn=deleted objects, windows_private_get_directory_replarea( prp->agmt) */ - - if ( slapi_filter_test( pb, e, filter_user_deleted, 0 ) == 0 ) - { - slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "entry %s marked for deletion\n", slapi_entry_get_ndn(e)); - - sdn = map_dn_user(slapi_entry_get_sdn(e),REPLICA_TYPE_MULTIMASTER, windows_private_get_directory_replarea( prp->agmt) ); - slapi_entry_set_sdn(e, sdn); - - slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "entry %s marked for deletion\n", slapi_entry_get_ndn(e)); - - - delete_user(e); /* CN is "garbled" if the entry is deleted */ - } - else if ( slapi_filter_test( pb, e, filter_group_deleted, 0 ) == 0 ) - { - slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "group %s marked for deletion\n", slapi_entry_get_ndn(e)); - - sdn = map_dn_group(slapi_entry_get_sdn(e),REPLICA_TYPE_MULTIMASTER, windows_private_get_directory_replarea( prp->agmt) ); - slapi_entry_set_sdn(e, sdn); - - slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "entry %s marked for deletion\n", slapi_entry_get_ndn(e)); - - delete_user(e); /* CN is "garbled" if the entry is deleted */ - - - } - /* must be in the previously specified container to be replicated, lest it is ignored */ - else if (slapi_sdn_isparent(windows_private_get_windows_replarea( prp->agmt ), slapi_entry_get_sdn(e)) ) - { - if (0 == slapi_filter_test( pb, e, filter_user, 0)) - { - sdn = map_dn_user(slapi_entry_get_sdn(e),REPLICA_TYPE_MULTIMASTER, windows_private_get_directory_replarea( prp->agmt) ); - map_entry_user(&e, REPLICA_TYPE_MULTIMASTER, NULL); - - slapi_entry_set_sdn(e, sdn); - /* if (windows_private_create_users(prp->ra)) */ - add_or_modify_user(e); - } - else if (0 == slapi_filter_test( pb, e, filter_group, 0)) - { - slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "group %s marked for addition\n", slapi_entry_get_ndn(e)); - - sdn = map_dn_group(slapi_entry_get_sdn(e),REPLICA_TYPE_MULTIMASTER, windows_private_get_directory_replarea( prp->agmt) ); - slapi_entry_set_sdn(e, sdn); - - map_entry_group(&e, REPLICA_TYPE_MULTIMASTER); - - slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "group %s marked for addition\n", slapi_entry_get_ndn(e)); - - add_or_modify_group(e); - } - else - { - slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "entry %s in %s ignored\n", slapi_entry_get_ndn(e), slapi_sdn_get_dn(windows_private_get_directory_replarea( prp->agmt)) ); - } - /* inside container */ - } - else - { - slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, - "entry %s ignored\n", slapi_entry_get_ndn(e)); - } - } - } -} - |