diff options
-rw-r--r-- | ldap/servers/plugins/replication/windows_private.c | 57 | ||||
-rw-r--r-- | ldap/servers/plugins/replication/windows_prot_private.h | 29 | ||||
-rw-r--r-- | ldap/servers/plugins/replication/windows_protocol_util.c | 92 | ||||
-rw-r--r-- | ldap/servers/plugins/replication/windowsrepl.h | 2 | ||||
-rw-r--r-- | ldap/servers/slapd/back-ldbm/ldbm_search.c | 50 |
5 files changed, 110 insertions, 120 deletions
diff --git a/ldap/servers/plugins/replication/windows_private.c b/ldap/servers/plugins/replication/windows_private.c index 1c2e0fbe..b0edf9d6 100644 --- a/ldap/servers/plugins/replication/windows_private.c +++ b/ldap/servers/plugins/replication/windows_private.c @@ -66,6 +66,10 @@ struct windowsprivate { char *windows_domain; int isnt4; int iswin2k3; + /* This filter is used to determine if an entry belongs to this agreement. We put it here + * so we only have to allocate each filter once instead of doing it every time we receive a change. */ + Slapi_Filter *directory_filter; /* Used for checking if local entries need to be sync'd to AD */ + Slapi_Filter *deleted_filter; /* Used for checking if an entry is an AD tombstone */ }; static int @@ -192,6 +196,8 @@ Dirsync_Private* windows_private_new() dp = (Dirsync_Private *)slapi_ch_calloc(sizeof(Dirsync_Private),1); dp->dirsync_maxattributecount = -1; + dp->directory_filter = NULL; + dp->deleted_filter = NULL; LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_new\n", 0, 0, 0 ); return dp; @@ -206,8 +212,8 @@ void windows_agreement_delete(Repl_Agmt *ra) PR_ASSERT(dp != NULL); - /* DBDB: need to free payoad here */ - + slapi_filter_free(dp->directory_filter, 1); + slapi_filter_free(dp->deleted_filter, 1); slapi_ch_free((void **)dp); LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_delete\n", 0, 0, 0 ); @@ -278,6 +284,53 @@ void windows_private_set_iswin2k3(const Repl_Agmt *ra, int isit) LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_set_iswin2k3\n", 0, 0, 0 ); } +/* Returns a copy of the Slapi_Filter pointer. The caller should not free it */ +Slapi_Filter* windows_private_get_directory_filter(const Repl_Agmt *ra) +{ + Dirsync_Private *dp; + + LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_get_directory_filter\n", 0, 0, 0 ); + + PR_ASSERT(ra); + + dp = (Dirsync_Private *) agmt_get_priv(ra); + PR_ASSERT (dp); + + if (dp->directory_filter == NULL) { + char *string_filter = slapi_ch_strdup("(&(|(objectclass=ntuser)(objectclass=ntgroup))(ntUserDomainId=*))"); + /* The filter gets freed in windows_agreement_delete() */ + dp->directory_filter = slapi_str2filter( string_filter ); + slapi_ch_free_string(&string_filter); + } + + LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_get_directory_filter\n", 0, 0, 0 ); + + return dp->directory_filter; +} + +/* Returns a copy of the Slapi_Filter pointer. The caller should not free it */ +Slapi_Filter* windows_private_get_deleted_filter(const Repl_Agmt *ra) +{ + Dirsync_Private *dp; + + LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_get_deleted_filter\n", 0, 0, 0 ); + + PR_ASSERT(ra); + + dp = (Dirsync_Private *) agmt_get_priv(ra); + PR_ASSERT (dp); + + if (dp->deleted_filter == NULL) { + char *string_filter = slapi_ch_strdup("(isdeleted=*)"); + /* The filter gets freed in windows_agreement_delete() */ + dp->deleted_filter = slapi_str2filter( string_filter ); + slapi_ch_free_string(&string_filter); + } + + LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_get_deleted_filter\n", 0, 0, 0 ); + + return dp->deleted_filter; +} /* Returns a copy of the Slapi_DN pointer, no need to free it */ const Slapi_DN* windows_private_get_windows_subtree (const Repl_Agmt *ra) diff --git a/ldap/servers/plugins/replication/windows_prot_private.h b/ldap/servers/plugins/replication/windows_prot_private.h index 68a9a5d9..736869b1 100644 --- a/ldap/servers/plugins/replication/windows_prot_private.h +++ b/ldap/servers/plugins/replication/windows_prot_private.h @@ -52,35 +52,6 @@ #define ACQUIRE_CONSUMER_WAS_UPTODATE 104 #define ACQUIRE_TRANSIENT_ERROR 105 -typedef struct windows_private_repl_protocol -{ - void (*delete)(struct windows_private_repl_protocol **); - void (*run)(struct windows_private_repl_protocol *); - int (*stop)(struct windows_private_repl_protocol *); - int (*status)(struct windows_private_repl_protocol *); - void (*notify_update)(struct windows_private_repl_protocol *); - void (*notify_agmt_changed)(struct windows_private_repl_protocol *); - void (*notify_window_opened)(struct windows_private_repl_protocol *); - void (*notify_window_closed)(struct windows_private_repl_protocol *); - void (*update_now)(struct windows_private_repl_protocol *); - PRLock *lock; - PRCondVar *cvar; - int stopped; - int terminate; - PRUint32 eventbits; - Repl_Connection *conn; - int last_acquire_response_code; - Repl_Agmt *agmt; - Object *replica_object; - void *private; - PRBool replica_acquired; -} Windows_Private_Repl_Protocol; - -/* -extern Windows_Private_Repl_Protocol *Windows_Inc_Protocol_new(); -extern Windows_Private_Repl_Protocol *Windows_Tot_Protocol_new(); -*/ - #define PROTOCOL_TERMINATION_NORMAL 301 #define PROTOCOL_TERMINATION_ABNORMAL 302 #define PROTOCOL_TERMINATION_NEEDS_TOTAL_UPDATE 303 diff --git a/ldap/servers/plugins/replication/windows_protocol_util.c b/ldap/servers/plugins/replication/windows_protocol_util.c index 3e28c4cc..2c95d11a 100644 --- a/ldap/servers/plugins/replication/windows_protocol_util.c +++ b/ldap/servers/plugins/replication/windows_protocol_util.c @@ -65,10 +65,12 @@ 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 windows_map_mods_for_replay(Private_Repl_Protocol *prp,LDAPMod **original_mods, LDAPMod ***returned_mods, int is_user, char** password); -static int is_subject_of_agreemeent_local(const Slapi_Entry *local_entry,const Repl_Agmt *ra); +static int is_subject_of_agreement_local(const Slapi_Entry *local_entry,const Repl_Agmt *ra); static int windows_create_remote_entry(Private_Repl_Protocol *prp,Slapi_Entry *original_entry, Slapi_DN *remote_sdn, Slapi_Entry **remote_entry, char** password); static int windows_get_local_entry(const Slapi_DN* local_dn,Slapi_Entry **local_entry); static int windows_get_local_entry_by_uniqueid(Private_Repl_Protocol *prp,const char* uniqueid,Slapi_Entry **local_entry); +static int windows_get_local_tombstone_by_uniqueid(Private_Repl_Protocol *prp,const char* uniqueid,Slapi_Entry **local_entry); +static int windows_search_local_entry_by_uniqueid(Private_Repl_Protocol *prp, const char *uniqueid, char ** attrs, Slapi_Entry **ret_entry, int tombstone, void * component_identity); static int map_entry_dn_outbound(Slapi_Entry *e, Slapi_DN **dn, Private_Repl_Protocol *prp, int *missing_entry, int want_guid); static char* extract_ntuserdomainid_from_entry(Slapi_Entry *e); static char* extract_container(const Slapi_DN *entry_dn, const Slapi_DN *suffix_dn); @@ -76,7 +78,7 @@ static int windows_get_remote_entry (Private_Repl_Protocol *prp, const Slapi_DN* static int windows_get_remote_tombstone(Private_Repl_Protocol *prp, const Slapi_DN* remote_dn,Slapi_Entry **remote_entry); static int windows_reanimate_tombstone(Private_Repl_Protocol *prp, const Slapi_DN* tombstone_dn, const char* new_dn); static const char* op2string (int op); -static int is_subject_of_agreemeent_remote(Slapi_Entry *e, const Repl_Agmt *ra); +static int is_subject_of_agreement_remote(Slapi_Entry *e, const Repl_Agmt *ra); static int map_entry_dn_inbound(Slapi_Entry *e, Slapi_DN **dn, const Repl_Agmt *ra); static int windows_update_remote_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,Slapi_Entry *local_entry); static int is_guid_dn(Slapi_DN *remote_dn); @@ -405,7 +407,7 @@ map_dn_values(Private_Repl_Protocol *prp,Slapi_ValueSet *original_values, Slapi_ int missing_entry = 0; Slapi_DN *remote_dn = NULL; /* Now map the DN */ - is_ours = is_subject_of_agreemeent_local(local_entry,prp->agmt); + is_ours = is_subject_of_agreement_local(local_entry,prp->agmt); if (is_ours) { map_entry_dn_outbound(local_entry,&remote_dn,prp,&missing_entry, 0 /* don't want GUID form here */); @@ -447,7 +449,7 @@ map_dn_values(Private_Repl_Protocol *prp,Slapi_ValueSet *original_values, Slapi_ retval = windows_get_remote_entry(prp,original_dn,&remote_entry); if (remote_entry && 0 == retval) { - is_ours = is_subject_of_agreemeent_remote(remote_entry,prp->agmt); + is_ours = is_subject_of_agreement_remote(remote_entry,prp->agmt); if (is_ours) { retval = map_entry_dn_inbound(remote_entry,&local_dn,prp->agmt); @@ -1121,10 +1123,16 @@ windows_replay_update(Private_Repl_Protocol *prp, slapi_operation_parameters *op local_dn = slapi_sdn_new_dn_byref( op->target_address.dn ); /* Since we have the target uniqueid in the op structure, let's - * fetch the local entry here using it. + * fetch the local entry here using it. We do not want to search + * across tombstone entries unless we are dealing with a delete + * operation here since searching across tombstones can be very + * inefficient as the tombstones build up. */ - - rc = windows_get_local_entry_by_uniqueid(prp, op->target_address.uniqueid, &local_entry); + if (op->operation_type != SLAPI_OPERATION_DELETE) { + rc = windows_get_local_entry_by_uniqueid(prp, op->target_address.uniqueid, &local_entry); + } else { + rc = windows_get_local_tombstone_by_uniqueid(prp, op->target_address.uniqueid, &local_entry); + } if (rc) { @@ -1135,7 +1143,7 @@ windows_replay_update(Private_Repl_Protocol *prp, slapi_operation_parameters *op goto error; } - is_ours = is_subject_of_agreemeent_local(local_entry, prp->agmt); + is_ours = is_subject_of_agreement_local(local_entry, prp->agmt); windows_is_local_entry_user_or_group(local_entry,&is_user,&is_group); slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, @@ -1839,25 +1847,15 @@ attr_compare_present(Slapi_Attr *a, Slapi_Attr *b) /* Is this entry a tombstone ? */ static int -is_tombstone(Slapi_Entry *e) +is_tombstone(Private_Repl_Protocol *prp, Slapi_Entry *e) { int retval = 0; - char *string_deleted = slapi_ch_strdup("(isdeleted=*)"); - - /* DBDB: we should allocate these filters once and keep them around for better performance */ - Slapi_Filter *filter_deleted = slapi_str2filter( string_deleted ); - - slapi_ch_free_string(&string_deleted); - /* DBDB: this should be one filter, the code originally tested separately and hasn't been fixed yet */ - if ( (slapi_filter_test_simple( e, filter_deleted ) == 0) ) + if ( (slapi_filter_test_simple( e, (Slapi_Filter*)windows_private_get_deleted_filter(prp->agmt) ) == 0) ) { retval = 1; } - slapi_filter_free(filter_deleted,1); - filter_deleted = NULL; - return retval; } @@ -2724,7 +2722,7 @@ error: * and does it have the right attribute values for sync ?) */ static int -is_subject_of_agreemeent_local(const Slapi_Entry *local_entry, const Repl_Agmt *ra) +is_subject_of_agreement_local(const Slapi_Entry *local_entry, const Repl_Agmt *ra) { int retval = 0; int is_in_subtree = 0; @@ -2741,23 +2739,16 @@ is_subject_of_agreemeent_local(const Slapi_Entry *local_entry, const Repl_Agmt * { /* Next test for the correct kind of entry */ if (local_entry) { - /* DBDB: we should allocate these filters once and keep them around for better performance */ - char *string_filter = slapi_ch_strdup("(&(|(objectclass=ntuser)(objectclass=ntgroup))(ntUserDomainId=*))"); - Slapi_Filter *filter = slapi_str2filter( string_filter ); - - slapi_ch_free_string(&string_filter); - if (slapi_filter_test_simple( (Slapi_Entry*)local_entry, filter ) == 0) + if (slapi_filter_test_simple( (Slapi_Entry*)local_entry, + (Slapi_Filter*)windows_private_get_directory_filter(ra)) == 0) { retval = 1; } - - slapi_filter_free(filter,1); - filter = NULL; } else { /* Error: couldn't find the entry */ slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, - "failed to find entry in is_subject_of_agreemeent_local: %d\n", retval); + "failed to find entry in is_subject_of_agreement_local: %d\n", retval); retval = 0; } } @@ -2767,7 +2758,7 @@ error: /* Tests if the entry is subject to our agreement (i.e. is it in the sync'ed subtree in AD and either a user or a group ?) */ static int -is_subject_of_agreemeent_remote(Slapi_Entry *e, const Repl_Agmt *ra) +is_subject_of_agreement_remote(Slapi_Entry *e, const Repl_Agmt *ra) { int retval = 0; int is_in_subtree = 0; @@ -3342,7 +3333,7 @@ int windows_process_total_entry(Private_Repl_Protocol *prp,Slapi_Entry *e) int missing_entry = 0; const Slapi_DN *local_dn = slapi_entry_get_sdn_const(e); /* First check if the entry is for us */ - is_ours = is_subject_of_agreemeent_local(e, prp->agmt); + is_ours = is_subject_of_agreement_local(e, prp->agmt); slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "%s: windows_process_total_entry: Looking dn=\"%s\" (%s)\n", agmt_get_long_name(prp->agmt), slapi_sdn_get_dn(slapi_entry_get_sdn_const(e)), is_ours ? "ours" : "not ours"); @@ -3366,8 +3357,8 @@ error: return retval; } -int -windows_search_local_entry_by_uniqueid(Private_Repl_Protocol *prp, const char *uniqueid, char ** attrs, Slapi_Entry **ret_entry , void * component_identity) +static int +windows_search_local_entry_by_uniqueid(Private_Repl_Protocol *prp, const char *uniqueid, char ** attrs, Slapi_Entry **ret_entry, int tombstone, void * component_identity) { Slapi_Entry **entries = NULL; Slapi_PBlock *int_search_pb = NULL; @@ -3377,7 +3368,15 @@ windows_search_local_entry_by_uniqueid(Private_Repl_Protocol *prp, const char *u *ret_entry = NULL; local_subtree = windows_private_get_directory_subtree(prp->agmt); - filter_string = PR_smprintf("(&(|(objectclass=*)(objectclass=ldapsubentry)(objectclass=nsTombstone))(nsUniqueid=%s))",uniqueid); + + /* Searching for tombstones can be expensive, so the caller needs to specify if + * we should search for a tombstone entry, or a normal entry. */ + if (tombstone) { + filter_string = PR_smprintf("(&(objectclass=nsTombstone)(nsUniqueid=%s))", uniqueid); + } else { + filter_string = PR_smprintf("(&(|(objectclass=*)(objectclass=ldapsubentry))(nsUniqueid=%s))",uniqueid); + } + int_search_pb = slapi_pblock_new (); slapi_search_internal_set_pb ( int_search_pb, slapi_sdn_get_dn(local_subtree), LDAP_SCOPE_SUBTREE, filter_string, attrs , @@ -3412,7 +3411,7 @@ windows_get_local_entry_by_uniqueid(Private_Repl_Protocol *prp,const char* uniqu { int retval = ENTRY_NOTFOUND; Slapi_Entry *new_entry = NULL; - windows_search_local_entry_by_uniqueid( prp, uniqueid, NULL, &new_entry, + windows_search_local_entry_by_uniqueid( prp, uniqueid, NULL, &new_entry, 0, /* Don't search tombstones */ repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION)); if (new_entry) { @@ -3423,6 +3422,21 @@ windows_get_local_entry_by_uniqueid(Private_Repl_Protocol *prp,const char* uniqu } static int +windows_get_local_tombstone_by_uniqueid(Private_Repl_Protocol *prp,const char* uniqueid,Slapi_Entry **local_entry) +{ + int retval = ENTRY_NOTFOUND; + Slapi_Entry *new_entry = NULL; + windows_search_local_entry_by_uniqueid( prp, uniqueid, NULL, &new_entry, 1, /* Search for tombstones */ + repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION)); + if (new_entry) + { + *local_entry = new_entry; + retval = 0; + } + return retval; +} + +static int windows_get_local_entry(const Slapi_DN* local_dn,Slapi_Entry **local_entry) { int retval = ENTRY_NOTFOUND; @@ -3446,7 +3460,7 @@ windows_process_dirsync_entry(Private_Repl_Protocol *prp,Slapi_Entry *e, int is_ /* deleted users are outside the 'correct container'. They live in cn=deleted objects, windows_private_get_directory_subtree( prp->agmt) */ - if (is_tombstone(e)) + if (is_tombstone(prp, e)) { rc = map_tombstone_dn_inbound(e, &local_sdn, prp->agmt); if ((0 == rc) && local_sdn) @@ -3461,7 +3475,7 @@ windows_process_dirsync_entry(Private_Repl_Protocol *prp,Slapi_Entry *e, int is_ } else { /* Is this entry one we should be interested in ? */ - if (is_subject_of_agreemeent_remote(e,prp->agmt)) + if (is_subject_of_agreement_remote(e,prp->agmt)) { /* First make its local DN */ rc = map_entry_dn_inbound(e, &local_sdn, prp->agmt); diff --git a/ldap/servers/plugins/replication/windowsrepl.h b/ldap/servers/plugins/replication/windowsrepl.h index a7d3267b..6928105a 100644 --- a/ldap/servers/plugins/replication/windowsrepl.h +++ b/ldap/servers/plugins/replication/windowsrepl.h @@ -68,6 +68,8 @@ int windows_private_get_isnt4(const Repl_Agmt *ra); void windows_private_set_isnt4(const Repl_Agmt *ra, int isit); int windows_private_get_iswin2k3(const Repl_Agmt *ra); void windows_private_set_iswin2k3(const Repl_Agmt *ra, int isit); +Slapi_Filter* windows_private_get_directory_filter(const Repl_Agmt *ra); +Slapi_Filter* windows_private_get_deleted_filter(const Repl_Agmt *ra); const char* windows_private_get_purl(const Repl_Agmt *ra); /* in windows_connection.c */ diff --git a/ldap/servers/slapd/back-ldbm/ldbm_search.c b/ldap/servers/slapd/back-ldbm/ldbm_search.c index e2202e40..3f0b3d35 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_search.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_search.c @@ -818,21 +818,6 @@ create_subtree_filter(Slapi_Filter* filter, int managedsait, Slapi_Filter** focr } -static int -nscpentrydn_check_filter(Slapi_Filter *f) -{ - if (!f || (f->f_choice != LDAP_FILTER_AND)) - return 0; /* Not nscpEntryDN filter */ - - if ( 0 == strcasecmp ( f->f_and->f_avtype, SLAPI_ATTR_NSCP_ENTRYDN)) { - return 1; /* Contains a nscpEntryDN filter */ - } else if ( 0 == strcasecmp ( f->f_and->f_next->f_avtype, SLAPI_ATTR_NSCP_ENTRYDN)) { - return 1; - } - return 0; /* Not nscpEntryDN filter */ -} - - /* * Build a candidate list for a SUBTREE scope search. */ @@ -886,41 +871,6 @@ subtree_candidates( idl_free(tmp); idl_free(descendants); } - /* - * If the search is initiated by the Directory Manager, - * and the filter includes objectclass=nsTombstone, - * then we union the candidate list with all the tombstone - * entries in this backend instance. - */ - if (has_tombstone_filter && isroot && !nscpentrydn_check_filter(filter)) - { - IDList *idl; - IDList *tmp= candidates; - struct slapi_filter f = {0}; - f.f_choice = LDAP_FILTER_EQUALITY; - f.f_avtype = "objectclass"; - f.f_avvalue.bv_val = SLAPI_ATTR_VALUE_TOMBSTONE; - f.f_avvalue.bv_len = strlen(SLAPI_ATTR_VALUE_TOMBSTONE); - f.f_next= NULL; - idl = filter_candidates( pb, be, NULL, &f, NULL, 0, err ); - - /* - * If that gave allids then try (nscpentrydn=*) instead. - * The nscpentrydn equality index contains all the tombstones - * and can be used to resolve a presence filter without - * hitting allids. - */ - if (idl && ALLIDS(idl)) { - idl_free(idl); - f.f_choice = LDAP_FILTER_PRESENT; - f.f_avtype = SLAPI_ATTR_NSCP_ENTRYDN; - idl = filter_candidates( pb, be, NULL, &f, NULL, 0, err ); - } - - candidates = idl_union( be, idl, tmp ); - idl_free( idl ); - idl_free( tmp ); - } return( candidates ); } |