浏览代码

Resolves: bug 457846
Bug Description: The Windows Sync API should have plug-in points
Reviewed by: nkinder (Thanks!)
Fix Description: Some additional changes to the api
1) added plugin points for begin update, end update, and agreement destruction
2) added debugging code to allow a regular DS to stand in for AD
3) fixed a couple of minor memory leaks
4) added the rest of the SLAPI DSE code to the public API to allow plugins to do dynamic configuration using the SLAPI public API
Platforms tested: RHEL5
Flag Day: no
Doc impact: yes - plugin guide

Rich Megginson 17 年之前
父节点
当前提交
446134bf3b

+ 6 - 6
ldap/servers/plugins/replication/windows_connection.c

@@ -1465,12 +1465,12 @@ windows_conn_replica_supports_dirsync(Repl_Connection *conn)
 
 
 	LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_replica_supports_dirsync\n", 0, 0, 0 );
 	LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_replica_supports_dirsync\n", 0, 0, 0 );
 
 
-#ifdef WINSYNC_TEST
-	/* used to fake out dirsync to think it's talking to a real ad when in fact
-	   it's just talking to another directory server */
-	conn->supports_dirsync = 1;
-	return CONN_SUPPORTS_DIRSYNC;
-#endif
+	if (getenv("WINSYNC_USE_DS")) {
+		/* used to fake out dirsync to think it's talking to a real ad when in fact
+		   it's just talking to another directory server */
+		conn->supports_dirsync = 1;
+		return CONN_SUPPORTS_DIRSYNC;
+	}
 
 
 	if (windows_conn_connected(conn))
 	if (windows_conn_connected(conn))
 	{
 	{

+ 12 - 0
ldap/servers/plugins/replication/windows_inc_protocol.c

@@ -812,6 +812,12 @@ windows_inc_run(Private_Repl_Protocol *prp)
 	      }   
 	      }   
 	    else
 	    else
 	      {
 	      {
+		/* call begin incremental update callback */
+		winsync_plugin_call_begin_update_cb(prp->agmt,
+						    windows_private_get_directory_subtree(prp->agmt),
+						    windows_private_get_windows_subtree(prp->agmt),
+						    0 /* is_total == FALSE */);
+
 		rc = send_updates(prp, ruv, &num_changes_sent);
 		rc = send_updates(prp, ruv, &num_changes_sent);
 		if (rc == UPDATE_NO_MORE_UPDATES)
 		if (rc == UPDATE_NO_MORE_UPDATES)
 		  {
 		  {
@@ -874,6 +880,12 @@ windows_inc_run(Private_Repl_Protocol *prp)
 	if (rc == UPDATE_TIMEOUT) {
 	if (rc == UPDATE_TIMEOUT) {
 	  windows_conn_disconnect(prp->conn);
 	  windows_conn_disconnect(prp->conn);
 	}
 	}
+	/* call end incremental update callback */
+	winsync_plugin_call_end_update_cb(prp->agmt,
+					  windows_private_get_directory_subtree(prp->agmt),
+					  windows_private_get_windows_subtree(prp->agmt),
+					  0 /* is_total == FALSE */);
+
 	if (rc == UPDATE_NO_MORE_UPDATES && num_changes_sent > 0)
 	if (rc == UPDATE_NO_MORE_UPDATES && num_changes_sent > 0)
 	{
 	{
 	  if (pausetime > 0)
 	  if (pausetime > 0)

+ 73 - 5
ldap/servers/plugins/replication/windows_private.c

@@ -47,8 +47,8 @@
 #include "repl5.h"
 #include "repl5.h"
 #include "slap.h"
 #include "slap.h"
 #include "slapi-plugin.h"
 #include "slapi-plugin.h"
-#include "windowsrepl.h"
 #include "winsync-plugin.h"
 #include "winsync-plugin.h"
+#include "windowsrepl.h"
 
 
 struct windowsprivate {
 struct windowsprivate {
   
   
@@ -217,6 +217,11 @@ void windows_agreement_delete(Repl_Agmt *ra)
 
 
 	PR_ASSERT(dp  != NULL);
 	PR_ASSERT(dp  != NULL);
 	
 	
+	winsync_plugin_call_destroy_agmt_cb(ra, dp->directory_subtree,
+										dp->windows_subtree);
+
+	slapi_sdn_free(&dp->directory_subtree);
+	slapi_sdn_free(&dp->windows_subtree);
 	slapi_filter_free(dp->directory_filter, 1);
 	slapi_filter_free(dp->directory_filter, 1);
 	slapi_filter_free(dp->deleted_filter, 1);
 	slapi_filter_free(dp->deleted_filter, 1);
 	slapi_entry_free(dp->raw_entry);
 	slapi_entry_free(dp->raw_entry);
@@ -538,9 +543,10 @@ LDAPControl* windows_private_dirsync_control(const Repl_Agmt *ra)
 
 
 	ber_printf( ber, "{iio}", dp->dirsync_flags, dp->dirsync_maxattributecount, dp->dirsync_cookie, dp->dirsync_cookie_len );
 	ber_printf( ber, "{iio}", dp->dirsync_flags, dp->dirsync_maxattributecount, dp->dirsync_cookie, dp->dirsync_cookie_len );
 
 
-#ifdef WINSYNC_TEST
-	iscritical = PR_FALSE;
-#endif
+	/* Use a regular directory server instead of a real AD - for testing */
+	if (getenv("WINSYNC_USE_DS")) {
+		iscritical = PR_FALSE;
+	}
 	slapi_build_control( REPL_DIRSYNC_CONTROL_OID, ber, iscritical, &control);
 	slapi_build_control( REPL_DIRSYNC_CONTROL_OID, ber, iscritical, &control);
 
 
 	ber_free(ber,1);
 	ber_free(ber,1);
@@ -563,7 +569,7 @@ void windows_private_update_dirsync_control(const Repl_Agmt *ra,LDAPControl **co
 	Dirsync_Private *dp;
 	Dirsync_Private *dp;
     int foundDirsyncControl;
     int foundDirsyncControl;
 	int i;
 	int i;
-	LDAPControl *dirsync;
+	LDAPControl *dirsync = NULL;
 	BerElement *ber;
 	BerElement *ber;
 	ber_int_t hasMoreData;
 	ber_int_t hasMoreData;
 	ber_int_t maxAttributeCount;
 	ber_int_t maxAttributeCount;
@@ -620,6 +626,7 @@ void windows_private_update_dirsync_control(const Repl_Agmt *ra,LDAPControl **co
 choke:
 choke:
 		ber_bvfree(serverCookie);
 		ber_bvfree(serverCookie);
 		ber_free(ber,1);
 		ber_free(ber,1);
+		ldap_control_free(dirsync);
 	}
 	}
 	else
 	else
 	{
 	{
@@ -1187,3 +1194,64 @@ winsync_plugin_call_can_add_entry_to_ad_cb(const Repl_Agmt *ra, const Slapi_Entr
 
 
     return (*thefunc)(windows_private_get_api_cookie(ra), local_entry, remote_dn);
     return (*thefunc)(windows_private_get_api_cookie(ra), local_entry, remote_dn);
 }
 }
+
+void
+winsync_plugin_call_begin_update_cb(const Repl_Agmt *ra, const Slapi_DN *ds_subtree,
+                                    const Slapi_DN *ad_subtree, int is_total)
+{
+    winsync_plugin_update_cb thefunc =
+        (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_BEGIN_UPDATE_CB]) ?
+        (winsync_plugin_update_cb)_WinSyncAPI[WINSYNC_PLUGIN_BEGIN_UPDATE_CB] :
+        NULL;
+
+    if (!thefunc) {
+        return;
+    }
+
+    (*thefunc)(windows_private_get_api_cookie(ra), ds_subtree, ad_subtree, is_total);
+
+    return;
+}
+
+void
+winsync_plugin_call_end_update_cb(const Repl_Agmt *ra, const Slapi_DN *ds_subtree,
+                                  const Slapi_DN *ad_subtree, int is_total)
+{
+    winsync_plugin_update_cb thefunc =
+        (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_END_UPDATE_CB]) ?
+        (winsync_plugin_update_cb)_WinSyncAPI[WINSYNC_PLUGIN_END_UPDATE_CB] :
+        NULL;
+
+    if (!thefunc) {
+        return;
+    }
+
+    (*thefunc)(windows_private_get_api_cookie(ra), ds_subtree, ad_subtree, is_total);
+
+    return;
+}
+
+void
+winsync_plugin_call_destroy_agmt_cb(const Repl_Agmt *ra,
+                                    const Slapi_DN *ds_subtree,
+                                    const Slapi_DN *ad_subtree)
+{
+    winsync_plugin_destroy_agmt_cb thefunc =
+        (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_DESTROY_AGMT_CB]) ?
+        (winsync_plugin_destroy_agmt_cb)_WinSyncAPI[WINSYNC_PLUGIN_DESTROY_AGMT_CB] :
+        NULL;
+
+    if (thefunc) {
+        (*thefunc)(windows_private_get_api_cookie(ra), ds_subtree, ad_subtree);
+    }
+
+    return;
+}
+
+/* #define WINSYNC_TEST_IPA */
+#ifdef WINSYNC_TEST_IPA
+
+#include "ipa-winsync.c"
+#include "ipa-winsync-config.c"
+
+#endif

+ 1 - 0
ldap/servers/plugins/replication/windows_protocol_util.c

@@ -2605,6 +2605,7 @@ map_entry_dn_outbound(Slapi_Entry *e, Slapi_DN **dn, Private_Repl_Protocol *prp,
 	{
 	{
 		*dn = new_dn;
 		*dn = new_dn;
 	}
 	}
+	slapi_ch_free_string(&guid);
 	return retval;
 	return retval;
 }
 }
 
 

+ 12 - 0
ldap/servers/plugins/replication/windows_tot_protocol.c

@@ -153,6 +153,12 @@ windows_tot_run(Private_Repl_Protocol *prp)
     
     
 	windows_private_null_dirsync_cookie(prp->agmt);
 	windows_private_null_dirsync_cookie(prp->agmt);
 
 
+	/* call begin total update callback */
+	winsync_plugin_call_begin_update_cb(prp->agmt,
+										windows_private_get_directory_subtree(prp->agmt),
+										windows_private_get_windows_subtree(prp->agmt),
+										1 /* is_total == TRUE */);
+
 	/* get everything */
 	/* get everything */
 	windows_dirsync_inc_run(prp);
 	windows_dirsync_inc_run(prp);
 	
 	
@@ -225,6 +231,12 @@ windows_tot_run(Private_Repl_Protocol *prp)
 		agmt_set_consumer_ruv(prp->agmt, starting_ruv );
 		agmt_set_consumer_ruv(prp->agmt, starting_ruv );
 	}
 	}
 
 
+	/* call end total update callback */
+	winsync_plugin_call_end_update_cb(prp->agmt,
+									  windows_private_get_directory_subtree(prp->agmt),
+									  windows_private_get_windows_subtree(prp->agmt),
+									  1 /* is_total == TRUE */);
+
 done:
 done:
 	if (starting_ruv)
 	if (starting_ruv)
 	{
 	{

+ 7 - 0
ldap/servers/plugins/replication/windowsrepl.h

@@ -153,6 +153,13 @@ void winsync_plugin_call_pre_ad_mod_user_mods_cb(const Repl_Agmt *ra, const Slap
 void winsync_plugin_call_pre_ad_mod_group_mods_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, const Slapi_DN *local_dn, LDAPMod * const *origmods, Slapi_DN *remote_dn, LDAPMod ***modstosend);
 void winsync_plugin_call_pre_ad_mod_group_mods_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, const Slapi_DN *local_dn, LDAPMod * const *origmods, Slapi_DN *remote_dn, LDAPMod ***modstosend);
 
 
 int winsync_plugin_call_can_add_entry_to_ad_cb(const Repl_Agmt *ra, const Slapi_Entry *local_entry, const Slapi_DN *remote_dn);
 int winsync_plugin_call_can_add_entry_to_ad_cb(const Repl_Agmt *ra, const Slapi_Entry *local_entry, const Slapi_DN *remote_dn);
+void winsync_plugin_call_begin_update_cb(const Repl_Agmt *ra, const Slapi_DN *ds_subtree,
+                                         const Slapi_DN *ad_subtree, int is_total);
+void winsync_plugin_call_end_update_cb(const Repl_Agmt *ra, const Slapi_DN *ds_subtree,
+                                       const Slapi_DN *ad_subtree, int is_total);
+void winsync_plugin_call_destroy_agmt_cb(const Repl_Agmt *ra,
+                                         const Slapi_DN *ds_subtree,
+                                         const Slapi_DN *ad_subtree);
 /*
 /*
   Call stack for all places where windows_LDAPMessage2Entry is called:
   Call stack for all places where windows_LDAPMessage2Entry is called:
 
 

+ 74 - 6
ldap/servers/plugins/replication/winsync-plugin.h

@@ -51,11 +51,12 @@
 #define WINSYNC_v1_0_GUID "CDA8F029-A3C6-4EBB-80B8-A2E183DB0481"
 #define WINSYNC_v1_0_GUID "CDA8F029-A3C6-4EBB-80B8-A2E183DB0481"
 
 
 /*
 /*
- * The plugin will define this callback in order to initialize itself.
- * The ds subtree and the ad subtree from the sync agreement are passed in.
- * These are read only.
- * The return value is private data to the plugin that will be passed back
- * at each callback
+ * This callback is called when a winsync agreement is created.
+ * The ds_subtree and ad_subtree from the agreement are read-only.
+ * The callback can allocate some private data to return.  If so
+ * the callback must define a winsync_plugin_destroy_agmt_cb so
+ * that the private data can be freed.  This private data is passed
+ * to every other callback function as the void *cookie argument.
  */
  */
 typedef void * (*winsync_plugin_init_cb)(const Slapi_DN *ds_subtree, const Slapi_DN *ad_subtree);
 typedef void * (*winsync_plugin_init_cb)(const Slapi_DN *ds_subtree, const Slapi_DN *ad_subtree);
 #define WINSYNC_PLUGIN_INIT_CB 1
 #define WINSYNC_PLUGIN_INIT_CB 1
@@ -160,6 +161,29 @@ typedef void (*winsync_pre_ad_mod_mods_cb)(void *cookie, const Slapi_Entry *rawe
 typedef int (*winsync_can_add_to_ad_cb)(void *cookie, const Slapi_Entry *local_entry, const Slapi_DN *remote_dn);
 typedef int (*winsync_can_add_to_ad_cb)(void *cookie, const Slapi_Entry *local_entry, const Slapi_DN *remote_dn);
 #define WINSYNC_PLUGIN_CAN_ADD_ENTRY_TO_AD_CB 16
 #define WINSYNC_PLUGIN_CAN_ADD_ENTRY_TO_AD_CB 16
 
 
+/*
+ * Callbacks called at begin and end of update
+ * 
+ * The ds subtree and the ad subtree from the sync agreement are passed in.
+ * These are read only.
+ * is_total will be true if this is a total update, or false if this
+ * is an incremental update
+ */
+typedef void (*winsync_plugin_update_cb)(void *cookie, const Slapi_DN *ds_subtree, const Slapi_DN *ad_subtree, int is_total);
+#define WINSYNC_PLUGIN_BEGIN_UPDATE_CB 17
+#define WINSYNC_PLUGIN_END_UPDATE_CB 18
+
+/*
+ * Callbacks called when the agreement is destroyed.
+ * 
+ * The ds subtree and the ad subtree from the sync agreement are passed in.
+ * These are read only.
+ * The plugin must define this function to free the cookie allocated
+ * in the init function, if any.
+ */
+typedef void (*winsync_plugin_destroy_agmt_cb)(void *cookie, const Slapi_DN *ds_subtree, const Slapi_DN *ad_subtree);
+#define WINSYNC_PLUGIN_DESTROY_AGMT_CB 19
+
 /*
 /*
   The following are sample code stubs to show how to implement
   The following are sample code stubs to show how to implement
   a plugin which uses this api
   a plugin which uses this api
@@ -418,6 +442,47 @@ test_winsync_can_add_entry_to_ad_cb(void *cbdata, const Slapi_Entry *local_entry
     return 0; /* false - do not allow entries to be added to ad */
     return 0; /* false - do not allow entries to be added to ad */
 }
 }
 
 
+static void
+test_winsync_begin_update_cb(void *cbdata, const Slapi_DN *ds_subtree,
+                             const Slapi_DN *ad_subtree, int is_total)
+{
+    slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+                    "--> test_winsync_begin_update_cb -- begin\n");
+
+    slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+                    "<-- test_winsync_begin_update_cb -- end\n");
+
+    return;
+}
+
+static void
+test_winsync_end_update_cb(void *cbdata, const Slapi_DN *ds_subtree,
+                           const Slapi_DN *ad_subtree, int is_total)
+{
+    slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+                    "--> test_winsync_end_update_cb -- begin\n");
+
+    slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+                    "<-- test_winsync_end_update_cb -- end\n");
+
+    return;
+}
+
+static void
+test_winsync_destroy_agmt_cb(void *cbdata, const Slapi_DN *ds_subtree,
+                             const Slapi_DN *ad_subtree)
+{
+    slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+                    "--> test_winsync_destroy_agmt_cb -- begin\n");
+
+    /* free(cbdata); */
+    
+    slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+                    "<-- test_winsync_destroy_agmt_cb -- end\n");
+
+    return;
+}
+
 /**
 /**
  * Plugin identifiers
  * Plugin identifiers
  */
  */
@@ -447,7 +512,10 @@ static void *test_winsync_api[] = {
     test_winsync_get_new_ds_group_dn_cb,
     test_winsync_get_new_ds_group_dn_cb,
     test_winsync_pre_ad_mod_user_mods_cb,
     test_winsync_pre_ad_mod_user_mods_cb,
     test_winsync_pre_ad_mod_group_mods_cb,
     test_winsync_pre_ad_mod_group_mods_cb,
-    test_winsync_can_add_entry_to_ad_cb
+    test_winsync_can_add_entry_to_ad_cb,
+    test_winsync_begin_update_cb,
+    test_winsync_end_update_cb,
+    test_winsync_destroy_agmt_cb
 };
 };
 
 
 static int
 static int

+ 14 - 0
ldap/servers/slapd/slapi-plugin.h

@@ -1256,6 +1256,20 @@ typedef int (*dseCallbackFn)(Slapi_PBlock *, Slapi_Entry *, Slapi_Entry *,
 #define SLAPI_DSE_CALLBACK_ERROR                (-1)
 #define SLAPI_DSE_CALLBACK_ERROR                (-1)
 #define SLAPI_DSE_CALLBACK_DO_NOT_APPLY (0)
 #define SLAPI_DSE_CALLBACK_DO_NOT_APPLY (0)
 
 
+/*
+ * Flags for slapi_config_register_callback() and
+ *		slapi_config_remove_callback()
+ */
+#define DSE_FLAG_PREOP          0x0001
+#define DSE_FLAG_POSTOP         0x0002
+
+/* This is the size of the returntext parameter passed to the config callback function,
+   which is the "char *" argument to dseCallbackFn above */
+#define SLAPI_DSE_RETURNTEXT_SIZE 512	/* for use by callback functions */
+
+int slapi_config_register_callback(int operation, int flags, const char *base, int scope, const char *filter, dseCallbackFn fn, void *fn_arg);
+int slapi_config_remove_callback(int operation, int flags, const char *base, int scope, const char *filter, dseCallbackFn fn);
+
 /******************************************************************************
 /******************************************************************************
  * Online tasks interface (to support import, export, etc)
  * Online tasks interface (to support import, export, etc)
  * After some cleanup, we could consider making these public.
  * After some cleanup, we could consider making these public.

+ 0 - 13
ldap/servers/slapd/slapi-private.h

@@ -1069,19 +1069,6 @@ int slapi_uniqueIDGenerateFromNameString(char **uId,
  * JCMREPL - Added for the replication plugin.
  * JCMREPL - Added for the replication plugin.
  */
  */
  
  
-/*
- * Flags for slapi_config_register_callback() and
- *		slapi_config_remove_callback()
- */
-#define DSE_FLAG_PREOP          0x0001
-#define DSE_FLAG_POSTOP         0x0002
-
-/* This is the size of the returntext parameter passed to the config callback function,
-   which is the "char *" argument to dseCallbackFn above */
-#define SLAPI_DSE_RETURNTEXT_SIZE 512	/* for use by callback functions */
-
-int slapi_config_register_callback(int operation, int flags, const char *base, int scope, const char *filter, dseCallbackFn fn, void *fn_arg);
-int slapi_config_remove_callback(int operation, int flags, const char *base, int scope, const char *filter, dseCallbackFn fn);
 int config_is_slapd_lite( void );
 int config_is_slapd_lite( void );
 void schema_expand_objectclasses_nolock( Slapi_Entry *e );
 void schema_expand_objectclasses_nolock( Slapi_Entry *e );