[Fedora-directory-commits] ldapserver/ldap/servers/slapd main.c, 1.22, 1.23 slap.h, 1.30, 1.31 slapi-plugin.h, 1.19, 1.20 slapi-private.h, 1.20, 1.21 task.c, 1.14, 1.15

Nathan Kinder (nkinder) fedora-directory-commits at redhat.com
Thu Apr 3 16:52:49 UTC 2008


Author: nkinder

Update of /cvs/dirsec/ldapserver/ldap/servers/slapd
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv18174/ldap/servers/slapd

Modified Files:
	main.c slap.h slapi-plugin.h slapi-private.h task.c 
Log Message:
Resolves: 439907
Summary: Enhanced SLAPI task API and ported existing tasks to use new API.



Index: main.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/main.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- main.c	18 Oct 2007 00:08:34 -0000	1.22
+++ main.c	3 Apr 2008 16:52:46 -0000	1.23
@@ -2118,7 +2118,7 @@
     pb.pb_ldif_files = ldif_file;
     pb.pb_ldif_include = db2ldif_include;
     pb.pb_ldif_exclude = db2ldif_exclude;
-    pb.pb_task_flags = TASK_RUNNING_FROM_COMMANDLINE;
+    pb.pb_task_flags = SLAPI_TASK_RUNNING_FROM_COMMANDLINE;
 #ifndef _WIN32
     main_setuid(slapdFrontendConfig->localuser);
 #endif
@@ -2245,7 +2245,7 @@
 	    pb.pb_ldif_dump_uniqueid = db2ldif_dump_uniqueid;
 		pb.pb_ldif_encrypt = importexport_encrypt;
 	    pb.pb_instance_name = *instp;
-	    pb.pb_task_flags = TASK_RUNNING_FROM_COMMANDLINE;
+	    pb.pb_task_flags = SLAPI_TASK_RUNNING_FROM_COMMANDLINE;
 		if (is_slapd_running())
 			pb.pb_server_running = 1;
 		else
@@ -2431,7 +2431,7 @@
     pb.pb_plugin = plugin;
     pb.pb_db2index_attrs = db2index_attrs;
     pb.pb_instance_name = cmd_line_instance_name;
-    pb.pb_task_flags = TASK_RUNNING_FROM_COMMANDLINE;
+    pb.pb_task_flags = SLAPI_TASK_RUNNING_FROM_COMMANDLINE;
 #ifndef _WIN32
     main_setuid(slapdFrontendConfig->localuser);
 #endif
@@ -2489,7 +2489,7 @@
 	pb.pb_plugin = backend_plugin;
 	pb.pb_instance_name = cmd_line_instance_name;
 	pb.pb_seq_val = archive_name;
-	pb.pb_task_flags = TASK_RUNNING_FROM_COMMANDLINE;
+	pb.pb_task_flags = SLAPI_TASK_RUNNING_FROM_COMMANDLINE;
 #ifndef _WIN32
 	main_setuid(slapdFrontendConfig->localuser);
 #endif
@@ -2539,7 +2539,7 @@
 	pb.pb_plugin = backend_plugin;
 	pb.pb_instance_name = cmd_line_instance_name;
 	pb.pb_seq_val = archive_name;
-	pb.pb_task_flags = TASK_RUNNING_FROM_COMMANDLINE;
+	pb.pb_task_flags = SLAPI_TASK_RUNNING_FROM_COMMANDLINE;
 #ifndef _WIN32
 	main_setuid(slapdFrontendConfig->localuser);
 #endif
@@ -2601,7 +2601,7 @@
     pb.pb_plugin = backend_plugin;
     pb.pb_seq_val = archive_name;
     pb.pb_seq_type = upgradedb_force;
-    pb.pb_task_flags = TASK_RUNNING_FROM_COMMANDLINE;
+    pb.pb_task_flags = SLAPI_TASK_RUNNING_FROM_COMMANDLINE;
     /* borrowing import code, so need to set up the import variables */
     pb.pb_ldif_generate_uniqueid = ldif2db_generate_uniqueid;
     pb.pb_ldif_namespaceid = ldif2db_namespaceid;
@@ -2656,7 +2656,7 @@
     pb.pb_seq_type = dbverify_verbose;
     pb.pb_plugin = backend_plugin;
     pb.pb_instance_name = (char *)cmd_line_instance_names;
-    pb.pb_task_flags = TASK_RUNNING_FROM_COMMANDLINE;
+    pb.pb_task_flags = SLAPI_TASK_RUNNING_FROM_COMMANDLINE;
     
     if ( backend_plugin->plg_dbverify != NULL ) {
         return_value = (*backend_plugin->plg_dbverify)( &pb );


Index: slap.h
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/slap.h,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -r1.30 -r1.31
--- slap.h	18 Oct 2007 01:22:29 -0000	1.30
+++ slap.h	3 Apr 2008 16:52:46 -0000	1.31
@@ -1283,6 +1283,27 @@
 #define SLAPD_POLL_FLAGS	(PR_POLL_READ)
 #endif
 
+/******************************************************************************
+ *  * Online tasks interface (to support import, export, etc)
+ *   * After some cleanup, we could consider making these public.
+ *    */
+struct slapi_task {
+    struct slapi_task *next;
+    char *task_dn;
+    int task_exitcode;          /* for the end user */
+    int task_state;             /* current state of task */
+    int task_progress;          /* number between 0 and task_work */
+    int task_work;              /* "units" of work to be done */
+    int task_flags;             /* (see above) */
+    char *task_status;          /* transient status info */
+    char *task_log;             /* appended warnings, etc */
+    void *task_private;         /* allow opaque data to be stashed in the task */
+    TaskCallbackFn cancel;      /* task has been cancelled by user */
+    TaskCallbackFn destructor;  /* task entry is being destroyed */
+    int task_refcount;
+} slapi_task;
+/* End of interface to support online tasks **********************************/
+
 typedef struct slapi_pblock {
 	/* common */
 	Slapi_Backend		*pb_backend;
@@ -2016,10 +2037,6 @@
 
 #include "intrinsics.h"
 
-/* task flag (pb_task_flags)*/
-#define TASK_RUNNING_AS_TASK		0x0
-#define TASK_RUNNING_FROM_COMMANDLINE	0x1
-
 /* printkey: import & export */
 #define	EXPORT_PRINTKEY			0x1
 #define	EXPORT_NOWRAP			0x2


Index: slapi-plugin.h
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/slapi-plugin.h,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- slapi-plugin.h	5 Oct 2007 23:31:07 -0000	1.19
+++ slapi-plugin.h	3 Apr 2008 16:52:46 -0000	1.20
@@ -149,9 +149,10 @@
 typedef struct slapi_mod		Slapi_Mod;
 typedef struct slapi_mods		Slapi_Mods;
 typedef struct slapi_componentid	Slapi_ComponentId;
+
 /* Online tasks interface (to support import, export, etc) */
-typedef struct _slapi_task		Slapi_Task;
-typedef int (*TaskCallbackFn)(Slapi_Task *task);
+typedef struct slapi_task		Slapi_Task;
+typedef void (*TaskCallbackFn)(Slapi_Task *task);
 
 /*
  * The default thread stacksize for nspr21 is 64k (except on IRIX!  It's 32k!).
@@ -1206,6 +1207,22 @@
 typedef int (*dseCallbackFn)(Slapi_PBlock *, Slapi_Entry *, Slapi_Entry *, 
                              int *, char*, void *);
 
+/*
+ * Note: DSE callback functions MUST return one of these three values:
+ *
+ *   SLAPI_DSE_CALLBACK_OK           -- no errors occurred; apply changes.
+ *   SLAPI_DSE_CALLBACK_ERROR        -- an error occurred; don't apply changes.
+ *   SLAPI_DSE_CALLBACK_DO_NOT_APPLY -- no error, but do not apply changes.
+ *
+ * SLAPI_DSE_CALLBACK_DO_NOT_APPLY should only be returned by modify
+ * callbacks (i.e., those registered with operation==SLAPI_OPERATION_MODIFY).
+ * A return value of SLAPI_DSE_CALLBACK_DO_NOT_APPLY is treated the same as
+ * SLAPI_DSE_CALLBACK_ERROR for all other operations.
+ */
+#define SLAPI_DSE_CALLBACK_OK                   (1)
+#define SLAPI_DSE_CALLBACK_ERROR                (-1)
+#define SLAPI_DSE_CALLBACK_DO_NOT_APPLY (0)
+
 /******************************************************************************
  * Online tasks interface (to support import, export, etc)
  * After some cleanup, we could consider making these public.
@@ -1217,10 +1234,26 @@
 #define SLAPI_TASK_FINISHED     2
 #define SLAPI_TASK_CANCELLED    3
 
+/* task flag (pb_task_flags)*/
+#define SLAPI_TASK_RUNNING_AS_TASK            0x0
+#define SLAPI_TASK_RUNNING_FROM_COMMANDLINE   0x1
+
 /* task flags (set by the task-control code) */
 #define SLAPI_TASK_DESTROYING   0x01    /* queued event for destruction */
 
 int slapi_task_register_handler(const char *name, dseCallbackFn func);
+void slapi_task_begin(Slapi_Task *task, int total_work);
+void slapi_task_inc_progress(Slapi_Task *task);
+void slapi_task_finish(Slapi_Task *task, int rc);
+void slapi_task_cancel(Slapi_Task *task, int rc);
+int slapi_task_get_state(Slapi_Task *task);
+void slapi_task_set_data(Slapi_Task *task, void *data);
+void * slapi_task_get_data(Slapi_Task *task);
+void slapi_task_inc_refcount(Slapi_Task *task);
+void slapi_task_dec_refcount(Slapi_Task *task);
+int slapi_task_get_refcount(Slapi_Task *task);
+void slapi_task_set_destructor_fn(Slapi_Task *task, TaskCallbackFn func);
+void slapi_task_set_cancel_fn(Slapi_Task *task, TaskCallbackFn func);
 void slapi_task_status_changed(Slapi_Task *task);
 void slapi_task_log_status(Slapi_Task *task, char *format, ...)
 #ifdef __GNUC__ 


Index: slapi-private.h
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/slapi-private.h,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -r1.20 -r1.21
--- slapi-private.h	18 Oct 2007 22:40:18 -0000	1.20
+++ slapi-private.h	3 Apr 2008 16:52:46 -0000	1.21
@@ -1060,22 +1060,6 @@
  */
  
 /*
- * Note: DSE callback functions MUST return one of these three values:
- *
- *   SLAPI_DSE_CALLBACK_OK           -- no errors occurred; apply changes.
- *   SLAPI_DSE_CALLBACK_ERROR        -- an error occurred; don't apply changes.
- *   SLAPI_DSE_CALLBACK_DO_NOT_APPLY -- no error, but do not apply changes.
- *
- * SLAPI_DSE_CALLBACK_DO_NOT_APPLY should only be returned by modify
- * callbacks (i.e., those registered with operation==SLAPI_OPERATION_MODIFY).
- * A return value of SLAPI_DSE_CALLBACK_DO_NOT_APPLY is treated the same as
- * SLAPI_DSE_CALLBACK_ERROR for all other operations.
- */
-#define SLAPI_DSE_CALLBACK_OK			(1)
-#define SLAPI_DSE_CALLBACK_ERROR		(-1)
-#define SLAPI_DSE_CALLBACK_DO_NOT_APPLY	(0)
-
-/*
  * Flags for slapi_config_register_callback() and
  *		slapi_config_remove_callback()
  */
@@ -1198,30 +1182,6 @@
 
 /***** End of items added for the replication plugin. ***********************/
 
-/******************************************************************************
- * Online tasks interface (to support import, export, etc)
- * After some cleanup, we could consider making these public.
- */
-struct _slapi_task {
-    struct _slapi_task *next;
-    char *task_dn;
-    int task_exitcode;          /* for the end user */
-    int task_state;             /* (see above) */
-    int task_progress;          /* number between 0 and task_work */
-    int task_work;              /* "units" of work to be done */
-    int task_flags;             /* (see above) */
-
-    /* it is the task's responsibility to allocate this memory & free it: */
-    char *task_status;          /* transient status info */
-    char *task_log;             /* appended warnings, etc */
-
-    void *task_private;         /* for use by backends */
-    TaskCallbackFn cancel;      /* task has been cancelled by user */
-    TaskCallbackFn destructor;  /* task entry is being destroyed */
-	int task_refcount;
-};
-/* End of interface to support online tasks **********************************/
-
 void    DS_Sleep(PRIntervalTime ticks);
 
 /* macro to specify the behavior of upgradedb */


Index: task.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/task.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- task.c	18 Oct 2007 00:08:34 -0000	1.14
+++ task.c	3 Apr 2008 16:52:46 -0000	1.15
@@ -47,6 +47,9 @@
 #include "slap.h"
 
 
+/***********************************
+ * Static Global Variables
+ ***********************************/
 /* don't panic, this is only used when creating new tasks or removing old
  * ones...
  */
@@ -54,7 +57,9 @@
 static PRLock *global_task_lock = NULL;
 static int shutting_down = 0;
 
-
+/***********************************
+ * Private Defines
+ ***********************************/
 #define TASK_BASE_DN      "cn=tasks, cn=config"
 #define TASK_IMPORT_DN    "cn=import, cn=tasks, cn=config"
 #define TASK_EXPORT_DN    "cn=export, cn=tasks, cn=config"
@@ -71,13 +76,398 @@
 
 #define DEFAULT_TTL     "120"   /* seconds */
 
+#define LOG_BUFFER              256
+/* if the cumul. log gets larger than this, it's truncated: */
+#define MAX_SCROLLBACK_BUFFER   8192
+
+#define NEXTMOD(_type, _val) do { \
+    modlist[cur].mod_op = LDAP_MOD_REPLACE; \
+    modlist[cur].mod_type = (_type); \
+    modlist[cur].mod_values = (char **)slapi_ch_malloc(2*sizeof(char *)); \
+    modlist[cur].mod_values[0] = (_val); \
+    modlist[cur].mod_values[1] = NULL; \
+    mod[cur] = &modlist[cur]; \
+    cur++; \
+} while (0)
 
+
+/***********************************
+ * Static Function Prototypes
+ ***********************************/
+static Slapi_Task *new_task(const char *dn);
+static void destroy_task(time_t when, void *arg);
 static int task_modify(Slapi_PBlock *pb, Slapi_Entry *e,
                        Slapi_Entry *eAfter, int *returncode, char *returntext, void *arg);
 static int task_deny(Slapi_PBlock *pb, Slapi_Entry *e,
                      Slapi_Entry *eAfter, int *returncode, char *returntext, void *arg);
-static int task_generic_destructor(Slapi_Task *task);
+static void task_generic_destructor(Slapi_Task *task);
+static const char *fetch_attr(Slapi_Entry *e, const char *attrname,
+                              const char *default_val);
+static Slapi_Entry *get_internal_entry(Slapi_PBlock *pb, char *dn);
+static void modify_internal_entry(char *dn, LDAPMod **mods);
+
+/***********************************
+ * Public Functions
+ ***********************************/ 
+/*
+ * slapi_new_task: create a new task, fill in DN, and setup modify callback
+ * argument:
+ *     dn: task dn
+ * result: 
+ *     Success: Slapi_Task object
+ *     Failure: NULL
+ */
+Slapi_Task *
+slapi_new_task(const char *dn)
+{
+    return new_task(dn);
+}
+
+/* slapi_destroy_task: destroy a task
+ * argument:
+ *     task: task to destroy
+ * result: 
+ *     none
+ */
+void
+slapi_destroy_task(void *arg)
+{
+    if (arg) {
+        destroy_task(1, arg);
+    }
+}
+
+/*
+ * Sets the initial task state and updated status
+ */
+void slapi_task_begin(Slapi_Task *task, int total_work)
+{
+    if (task) {
+        task->task_work = total_work;
+        task->task_progress = 0;
+        task->task_state = SLAPI_TASK_RUNNING;
+        slapi_task_status_changed(task);
+    }
+}
+
+/*
+ * Increments task progress and updates status
+ */
+void slapi_task_inc_progress(Slapi_Task *task)
+{
+    if (task) {
+        task->task_progress++;
+        slapi_task_status_changed(task);
+    }
+}
+
+/*
+ * Sets completed task state and updates status
+ */
+void slapi_task_finish(Slapi_Task *task, int rc)
+{
+    if (task) {
+        task->task_exitcode = rc;
+        task->task_state = SLAPI_TASK_FINISHED;
+        slapi_task_status_changed(task);
+    }
+}
+
+/*
+ * Cancels a task
+ */
+void slapi_task_cancel(Slapi_Task *task, int rc)
+{
+    if (task) {
+        task->task_exitcode = rc;
+        task->task_state = SLAPI_TASK_CANCELLED;
+        slapi_task_status_changed(task);
+    }
+}
+
+/*
+ * Get the current state of a task
+ */
+int slapi_task_get_state(Slapi_Task *task)
+{
+    if (task) {
+        return task->task_state;
+    }
+}
 
+/* this changes the 'nsTaskStatus' value, which is transient (anything logged
+ * here wipes out any previous status)
+ */
+void slapi_task_log_status(Slapi_Task *task, char *format, ...)
+{
+    va_list ap;
+
+    if (! task->task_status)
+        task->task_status = (char *)slapi_ch_malloc(10 * LOG_BUFFER);
+    if (! task->task_status)
+        return;        /* out of memory? */
+
+    va_start(ap, format);
+    PR_vsnprintf(task->task_status, (10 * LOG_BUFFER), format, ap);
+    va_end(ap);
+    slapi_task_status_changed(task);
+}
+
+/* this adds a line to the 'nsTaskLog' value, which is cumulative (anything
+ * logged here is added to the end)
+ */
+void slapi_task_log_notice(Slapi_Task *task, char *format, ...)
+{
+    va_list ap;
+    char buffer[LOG_BUFFER];
+    size_t len;
+
+    va_start(ap, format);
+    PR_vsnprintf(buffer, LOG_BUFFER, format, ap);
+    va_end(ap);
+
+    len = 2 + strlen(buffer) + (task->task_log ? strlen(task->task_log) : 0);
+    if ((len > MAX_SCROLLBACK_BUFFER) && task->task_log) {
+        size_t i;
+        char *newbuf;
+
+        /* start from middle of buffer, and find next linefeed */
+        i = strlen(task->task_log)/2;
+        while (task->task_log[i] && (task->task_log[i] != '\n'))
+            i++;
+        if (task->task_log[i])
+            i++;
+        len = strlen(task->task_log) - i + 2 + strlen(buffer);
+        newbuf = (char *)slapi_ch_malloc(len);
+        if (! newbuf)
+            return;    /* out of memory? */
+        strcpy(newbuf, task->task_log + i);
+        slapi_ch_free((void **)&task->task_log);
+        task->task_log = newbuf;
+    } else {
+        if (! task->task_log) {
+            task->task_log = (char *)slapi_ch_malloc(len);
+            task->task_log[0] = 0;
+        } else {
+            task->task_log = (char *)slapi_ch_realloc(task->task_log, len);
+        }
+        if (! task->task_log)
+            return;    /* out of memory? */
+    }
+
+    if (task->task_log[0])
+        strcat(task->task_log, "\n");
+    strcat(task->task_log, buffer);
+
+    slapi_task_status_changed(task);
+}
+
+/* update attributes in the entry under "cn=tasks" to match the current
+ * status of the task. */
+void slapi_task_status_changed(Slapi_Task *task)
+{
+    LDAPMod modlist[20];
+    LDAPMod *mod[20];
+    int cur = 0, i;
+    char s1[20], s2[20], s3[20];
+
+    if (shutting_down) {
+        /* don't care about task status updates anymore */
+        return;
+    }
+
+    NEXTMOD(TASK_LOG_NAME, task->task_log);
+    NEXTMOD(TASK_STATUS_NAME, task->task_status);
+    sprintf(s1, "%d", task->task_exitcode);
+    sprintf(s2, "%d", task->task_progress);
+    sprintf(s3, "%d", task->task_work);
+    NEXTMOD(TASK_PROGRESS_NAME, s2);
+    NEXTMOD(TASK_WORK_NAME, s3);
+    /* only add the exit code when the job is done */
+    if ((task->task_state == SLAPI_TASK_FINISHED) ||
+        (task->task_state == SLAPI_TASK_CANCELLED)) {
+        NEXTMOD(TASK_EXITCODE_NAME, s1);
+        /* make sure the console can tell the task has ended */
+        if (task->task_progress != task->task_work) {
+            task->task_progress = task->task_work;
+        }
+    }
+
+    mod[cur] = NULL;
+    modify_internal_entry(task->task_dn, mod);
+
+    for (i = 0; i < cur; i++)
+        slapi_ch_free((void **)&modlist[i].mod_values);
+
+    if (((task->task_state == SLAPI_TASK_FINISHED) ||
+         (task->task_state == SLAPI_TASK_CANCELLED)) &&
+        !(task->task_flags & SLAPI_TASK_DESTROYING)) {
+        Slapi_PBlock *pb = slapi_pblock_new();
+        Slapi_Entry *e;
+        int ttl;
+        time_t expire;
+
+        e = get_internal_entry(pb, task->task_dn);
+        if (e == NULL)
+            return;
+        ttl = atoi(fetch_attr(e, "ttl", DEFAULT_TTL));
+        if (ttl > 3600)
+            ttl = 3600;         /* be reasonable. */
+        expire = time(NULL) + ttl;
+        task->task_flags |= SLAPI_TASK_DESTROYING;
+        /* queue an event to destroy the state info */
+        slapi_eq_once(destroy_task, (void *)task, expire);
+
+        slapi_free_search_results_internal(pb);
+        slapi_pblock_destroy(pb);
+    }
+}
+
+/*
+ * Stash some opaque task specific data in the task for later use.
+ */
+void slapi_task_set_data(Slapi_Task *task, void *data)
+{
+    if (task) {
+        task->task_private = data;
+    }
+}
+
+/*
+ * Retrieve some opaque task specific data from the task.
+ */
+void * slapi_task_get_data(Slapi_Task *task)
+{
+    if (task) {
+        return task->task_private;
+    }
+}
+
+/*
+ * Increment the task reference count
+ */
+void slapi_task_inc_refcount(Slapi_Task *task)
+{
+    if (task) {
+        task->task_refcount++;
+    }
+}
+
+/*
+ * Decrement the task reference count
+ */
+void slapi_task_dec_refcount(Slapi_Task *task)
+{
+    if (task) {
+        task->task_refcount--;
+    }
+}
+
+/*
+ * Returns the task reference count
+ */
+int slapi_task_get_refcount(Slapi_Task *task)
+{
+    if (task) {
+        return task->task_refcount;
+    }
+}
+
+/* name is, for example, "import" */
+int slapi_task_register_handler(const char *name, dseCallbackFn func)
+{
+    char *dn = NULL;
+    Slapi_PBlock *pb = NULL;
+    Slapi_Operation *op;
+    LDAPMod *mods[3];
+    LDAPMod mod[3];
+    const char *objectclass[3];
+    const char *cnvals[2];
+    int ret = -1;
+    int x;
+
+    dn = slapi_ch_smprintf("cn=%s, %s", name, TASK_BASE_DN);
+    if (dn == NULL) {
+        goto out;
+    }
+
+    pb = slapi_pblock_new();
+    if (pb == NULL) {
+        goto out;
+    }
+
+    /* this is painful :( */
+    mods[0] = &mod[0];
+    mod[0].mod_op = LDAP_MOD_ADD;
+    mod[0].mod_type = "objectClass";
+    mod[0].mod_values = (char **)objectclass;
+    objectclass[0] = "top";
+    objectclass[1] = "extensibleObject";
+    objectclass[2] = NULL;
+    mods[1] = &mod[1];
+    mod[1].mod_op = LDAP_MOD_ADD;
+    mod[1].mod_type = "cn";
+    mod[1].mod_values = (char **)cnvals;
+    cnvals[0] = name;
+    cnvals[1] = NULL;
+    mods[2] = NULL;
+    slapi_add_internal_set_pb(pb, dn, mods, NULL,
+                              plugin_get_default_component_id(), 0);
+    x = 1;
+    slapi_pblock_set(pb, SLAPI_DSE_DONT_WRITE_WHEN_ADDING, &x);
+    /* Make sure these adds don't appear in the audit and change logs */
+    slapi_pblock_get(pb, SLAPI_OPERATION, &op);
+    operation_set_flag(op, OP_FLAG_ACTION_NOLOG);
+
+    slapi_add_internal_pb(pb);
+    slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &x);
+    if ((x != LDAP_SUCCESS) && (x != LDAP_ALREADY_EXISTS)) {
+        LDAPDebug(LDAP_DEBUG_ANY,
+                  "Can't create task node '%s' (error %d)\n",
+                  name, x, 0);
+        ret = x;
+        goto out;
+    }
+
+    /* register add callback */
+    slapi_config_register_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP,
+                                   dn, LDAP_SCOPE_SUBTREE, "(objectclass=*)", func, NULL);
+    /* deny modify/delete of the root task entry */
+    slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP,
+                                   dn, LDAP_SCOPE_BASE, "(objectclass=*)", task_deny, NULL);
+    slapi_config_register_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP,
+                                   dn, LDAP_SCOPE_BASE, "(objectclass=*)", task_deny, NULL);
+
+    ret = 0;
+
+out:
+    if (dn) {
+        slapi_ch_free((void **)&dn);
+    }
+    if (pb) {
+        slapi_pblock_destroy(pb);
+    }
+    return ret;
+}
+
+void slapi_task_set_destructor_fn(Slapi_Task *task, TaskCallbackFn func)
+{
+    if (task) {
+        task->destructor = func;
+    }
+}
+
+void slapi_task_set_cancel_fn(Slapi_Task *task, TaskCallbackFn func)
+{
+    if (task) {
+        task->cancel = func;
+    }
+}
+
+
+/***********************************
+ * Static Helper Functions
+ ***********************************/
 /* create a new task, fill in DN, and setup modify callback */
 static Slapi_Task *
 new_task(const char *dn)
@@ -92,7 +482,11 @@
     PR_Unlock(global_task_lock);
 
     task->task_dn = slapi_ch_strdup(dn);
-    task->destructor = task_generic_destructor;
+    task->task_state = SLAPI_TASK_SETUP;
+    task->task_flags = SLAPI_TASK_RUNNING_AS_TASK;
+    task->destructor = NULL;
+    task->cancel = NULL;
+    task->task_private = NULL;
     slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
                                    LDAP_SCOPE_BASE, "(objectclass=*)", task_modify, (void *)task);
     slapi_config_register_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP, dn,
@@ -100,8 +494,8 @@
     /* don't add entries under this one */
 #if 0
     /* don't know why, but this doesn't work.  it makes the current add
-     * operation fail. :(
-     */
+ *      * operation fail. :(
+ *           */
     slapi_config_register_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
                                    LDAP_SCOPE_SUBTREE, "(objectclass=*)", task_deny, NULL);
 #endif
@@ -117,8 +511,13 @@
     Slapi_Task *t1;
     Slapi_PBlock *pb = slapi_pblock_new();
 
-    if (task->destructor != NULL)
+    /* Call the custom destructor callback if one was provided,
+     * then perform the internal task destruction. */
+    if (task->destructor != NULL) {
         (*task->destructor)(task);
+    }
+
+    task_generic_destructor(task);
 
     /* if when == 0, we're already locked (called during shutdown) */
     if (when != 0) {
@@ -141,45 +540,16 @@
     slapi_config_remove_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP,
                                  task->task_dn, LDAP_SCOPE_BASE, "(objectclass=*)", task_modify);
     slapi_config_remove_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP,
-                                 task->task_dn, LDAP_SCOPE_BASE, "(objectclass=*)", task_deny);
-    slapi_delete_internal_set_pb(pb, task->task_dn, NULL, NULL,
-                                 (void *)plugin_get_default_component_id(), 0);
-
-    slapi_delete_internal_pb(pb);
-    slapi_pblock_destroy(pb);
-
-    slapi_ch_free((void **)&task->task_dn);
-    slapi_ch_free((void **)&task);
-}
-
-/*
- * slapi_new_task: create a new task, fill in DN, and setup modify callback
- * argument:
- *     dn: task dn
- * result: 
- *     Success: Slapi_Task object
- *     Failure: NULL
- */
-Slapi_Task *
-slapi_new_task(const char *dn)
-{
-    return new_task(dn);
-}
-
-/* slapi_destroy_task: destroy a task
- * argument:
- *     task: task to destroy
- * result: 
- *     none
- */
-void
-slapi_destroy_task(void *arg)
-{
-    destroy_task(1, arg);
-}
+                                 task->task_dn, LDAP_SCOPE_BASE, "(objectclass=*)", task_deny);
+    slapi_delete_internal_set_pb(pb, task->task_dn, NULL, NULL,
+                                 (void *)plugin_get_default_component_id(), 0);
 
-/**********  some useful helper functions  **********/
+    slapi_delete_internal_pb(pb);
+    slapi_pblock_destroy(pb);
 
+    slapi_ch_free((void **)&task->task_dn);
+    slapi_ch_free((void **)&task);
+}
 
 /* extract a single value from the entry (as a string) -- if it's not in the
  * entry, the default will be returned (which can be NULL).
@@ -268,81 +638,7 @@
     } while (ret != LDAP_SUCCESS);
 }
 
-
-/**********  helper functions for dealing with task logging  **********/
-
-#define LOG_BUFFER		256
-/* if the cumul. log gets larger than this, it's truncated: */
-#define MAX_SCROLLBACK_BUFFER	8192
-
-/* this changes the 'nsTaskStatus' value, which is transient (anything logged
- * here wipes out any previous status)
- */
-void slapi_task_log_status(Slapi_Task *task, char *format, ...)
-{
-    va_list ap;
-
-    if (! task->task_status)
-        task->task_status = (char *)slapi_ch_malloc(10 * LOG_BUFFER);
-    if (! task->task_status)
-        return;        /* out of memory? */
-
-    va_start(ap, format);
-    PR_vsnprintf(task->task_status, (10 * LOG_BUFFER), format, ap);
-    va_end(ap);
-    slapi_task_status_changed(task);
-}
-
-/* this adds a line to the 'nsTaskLog' value, which is cumulative (anything
- * logged here is added to the end)
- */
-void slapi_task_log_notice(Slapi_Task *task, char *format, ...)
-{
-    va_list ap;
-    char buffer[LOG_BUFFER];
-    size_t len;
-
-    va_start(ap, format);
-    PR_vsnprintf(buffer, LOG_BUFFER, format, ap);
-    va_end(ap);
-
-    len = 2 + strlen(buffer) + (task->task_log ? strlen(task->task_log) : 0);
-    if ((len > MAX_SCROLLBACK_BUFFER) && task->task_log) {
-        size_t i;
-        char *newbuf;
-
-        /* start from middle of buffer, and find next linefeed */
-        i = strlen(task->task_log)/2;
-        while (task->task_log[i] && (task->task_log[i] != '\n'))
-            i++;
-        if (task->task_log[i])
-            i++;
-        len = strlen(task->task_log) - i + 2 + strlen(buffer);
-        newbuf = (char *)slapi_ch_malloc(len);
-        if (! newbuf)
-            return;    /* out of memory? */
-        strcpy(newbuf, task->task_log + i);
-        slapi_ch_free((void **)&task->task_log);
-        task->task_log = newbuf;
-    } else {
-        if (! task->task_log) {
-            task->task_log = (char *)slapi_ch_malloc(len);
-            task->task_log[0] = 0;
-        } else {
-            task->task_log = (char *)slapi_ch_realloc(task->task_log, len);
-        }        
-        if (! task->task_log)
-            return;    /* out of memory? */
-    }
-
-    if (task->task_log[0])
-        strcat(task->task_log, "\n");
-    strcat(task->task_log, buffer);
-
-    slapi_task_status_changed(task);
-}
-
-static int task_generic_destructor(Slapi_Task *task)
+static void task_generic_destructor(Slapi_Task *task)
 {
     if (task->task_log) {
         slapi_ch_free((void **)&task->task_log);
@@ -351,7 +647,6 @@
         slapi_ch_free((void **)&task->task_status);
     }
     task->task_log = task->task_status = NULL;
-    return 0;
 }
 
 
@@ -553,13 +848,12 @@
     }
 
     /* allocate new task now */
-    task = new_task(slapi_entry_get_ndn(e));
+    task = slapi_new_task(slapi_entry_get_ndn(e));
     if (task == NULL) {
         LDAPDebug(LDAP_DEBUG_ANY, "unable to allocate new task!\n", 0, 0, 0);
         rv = LDAP_OPERATIONS_ERROR;
         goto out;
     }
-    task->task_state = SLAPI_TASK_SETUP;
 
     memset(&mypb, 0, sizeof(mypb));
     mypb.pb_backend = be;
@@ -575,7 +869,7 @@
     mypb.pb_ldif_include = include;
     mypb.pb_ldif_exclude = exclude;
     mypb.pb_task = task;
-    mypb.pb_task_flags = TASK_RUNNING_AS_TASK;
+    mypb.pb_task_flags = SLAPI_TASK_RUNNING_AS_TASK;
     if (NULL != encrypt_on_import && 0 == strcasecmp(encrypt_on_import, "true") ) {
         mypb.pb_ldif_encrypt = 1;
     }
@@ -618,10 +912,7 @@
     g_incr_active_threadcnt();
     for (count = 0, inp = instance_names; *inp; inp++, count++)
         ;
-    task->task_work = count;
-    task->task_progress = 0;
-    task->task_state = SLAPI_TASK_RUNNING;
-    slapi_task_status_changed(task);
+    slapi_task_begin(task, count);
 
     for (inp = instance_names; *inp; inp++) {
         int release_me = 0;
@@ -693,8 +984,7 @@
         if (rv != 0)
             break;
 
-        task->task_progress++;
-        slapi_task_status_changed(task);
+        slapi_task_inc_progress(task);
     }
 
     /* free the memory now */
@@ -712,9 +1002,7 @@
         LDAPDebug(LDAP_DEBUG_ANY, "Export failed.\n", 0, 0, 0);
     }
 
-    task->task_exitcode = rv;
-    task->task_state = SLAPI_TASK_FINISHED;
-    slapi_task_status_changed(task);
+    slapi_task_finish(task, rv);
     g_decr_active_threadcnt();
 }
 
@@ -888,16 +1176,13 @@
     }
 
     /* allocate new task now */
-    task = new_task(slapi_entry_get_ndn(e));
+    task = slapi_new_task(slapi_entry_get_ndn(e));
     if (task == NULL) {
         LDAPDebug(LDAP_DEBUG_ANY, "unable to allocate new task!\n", 0, 0, 0);
         *returncode = LDAP_OPERATIONS_ERROR;
         rv = SLAPI_DSE_CALLBACK_ERROR;
         goto out;
     }
-    task->task_state = SLAPI_TASK_SETUP;
-    task->task_work = instance_cnt;
-    task->task_progress = 0;
 
     mypb = slapi_pblock_new();
     if (mypb == NULL) {
@@ -914,7 +1199,7 @@
     /* horrible hack */
     mypb->pb_instance_name = (char *)instance_names;
     mypb->pb_task = task;
-    mypb->pb_task_flags = TASK_RUNNING_AS_TASK;
+    mypb->pb_task_flags = SLAPI_TASK_RUNNING_AS_TASK;
     if (NULL != decrypt_on_export && 0 == strcasecmp(decrypt_on_export, "true") ) {
         mypb->pb_ldif_encrypt = 1;
     }
@@ -957,10 +1242,7 @@
     int rv;
 
     g_incr_active_threadcnt();
-    task->task_work = 1;
-    task->task_progress = 0;
-    task->task_state = SLAPI_TASK_RUNNING;
-    slapi_task_status_changed(task);
+    slapi_task_begin(task, 1);
 
     slapi_task_log_notice(task, "Beginning backup of '%s'",
                           pb->pb_plugin->plg_name);
@@ -978,11 +1260,7 @@
         LDAPDebug(LDAP_DEBUG_ANY, "Backup finished.\n", 0, 0, 0);
     }
 
-    task->task_progress = 1;
-    task->task_exitcode = rv;
-    task->task_state = SLAPI_TASK_FINISHED;
-    slapi_task_status_changed(task);
-
+    slapi_task_finish(task, rv);
     slapi_ch_free((void **)&pb->pb_seq_val);
     slapi_pblock_destroy(pb);
     g_decr_active_threadcnt();
@@ -1048,16 +1326,13 @@
     }
 
     /* allocate new task now */
-    task = new_task(slapi_entry_get_ndn(e));
+    task = slapi_new_task(slapi_entry_get_ndn(e));
     if (task == NULL) {
         LDAPDebug(LDAP_DEBUG_ANY, "unable to allocate new task!\n", 0, 0, 0);
         *returncode = LDAP_OPERATIONS_ERROR;
         rv = SLAPI_DSE_CALLBACK_ERROR;
         goto out;
     }
-    task->task_state = SLAPI_TASK_SETUP;
-    task->task_work = 1;
-    task->task_progress = 0;
 
     mypb = slapi_pblock_new();
     if (mypb == NULL) {
@@ -1068,7 +1343,7 @@
     mypb->pb_seq_val = slapi_ch_strdup(archive_dir);
     mypb->pb_plugin = be->be_database;
     mypb->pb_task = task;
-    mypb->pb_task_flags = TASK_RUNNING_AS_TASK;
+    mypb->pb_task_flags = SLAPI_TASK_RUNNING_AS_TASK;
 
     /* start the backup as a separate thread */
     thread = PR_CreateThread(PR_USER_THREAD, task_backup_thread,
@@ -1102,10 +1377,7 @@
     int rv;
 
     g_incr_active_threadcnt();
-    task->task_work = 1;
-    task->task_progress = 0;
-    task->task_state = SLAPI_TASK_RUNNING;
-    slapi_task_status_changed(task);
+    slapi_task_begin(task, 1);
 
     slapi_task_log_notice(task, "Beginning restore to '%s'",
                           pb->pb_plugin->plg_name);
@@ -1123,11 +1395,7 @@
         LDAPDebug(LDAP_DEBUG_ANY, "Restore finished.\n", 0, 0, 0);
     }
 
-    task->task_progress = 1;
-    task->task_exitcode = rv;
-    task->task_state = SLAPI_TASK_FINISHED;
-    slapi_task_status_changed(task);
-
+    slapi_task_finish(task, rv);
     slapi_ch_free((void **)&pb->pb_seq_val);
     slapi_pblock_destroy(pb);
     g_decr_active_threadcnt();
@@ -1199,16 +1467,13 @@
     }
 
     /* allocate new task now */
-    task = new_task(slapi_entry_get_ndn(e));
+    task = slapi_new_task(slapi_entry_get_ndn(e));
     if (task == NULL) {
         LDAPDebug(LDAP_DEBUG_ANY, "unable to allocate new task!\n", 0, 0, 0);
         *returncode = LDAP_OPERATIONS_ERROR;
         rv = SLAPI_DSE_CALLBACK_ERROR;
         goto out;
     }
-    task->task_state = SLAPI_TASK_SETUP;
-    task->task_work = 1;
-    task->task_progress = 0;
 
     mypb = slapi_pblock_new();
     if (mypb == NULL) {
@@ -1221,7 +1486,7 @@
     if (NULL != instance_name)
         mypb->pb_instance_name = slapi_ch_strdup(instance_name);
     mypb->pb_task = task;
-    mypb->pb_task_flags = TASK_RUNNING_AS_TASK;
+    mypb->pb_task_flags = SLAPI_TASK_RUNNING_AS_TASK;
 
     /* start the restore as a separate thread */
     thread = PR_CreateThread(PR_USER_THREAD, task_restore_thread,
@@ -1255,10 +1520,7 @@
     int rv;
 
     g_incr_active_threadcnt();
-    task->task_work = 1;
-    task->task_progress = 0;
-    task->task_state = SLAPI_TASK_RUNNING;
-    slapi_task_status_changed(task);
+    slapi_task_begin(task, 1);
 
     rv = (*pb->pb_plugin->plg_db2index)(pb);
     if (rv != 0) {
@@ -1267,11 +1529,7 @@
         LDAPDebug(LDAP_DEBUG_ANY, "Index failed (error %d)\n", rv, 0, 0);
     }
 
-    task->task_progress = task->task_work;
-    task->task_exitcode = rv;
-    task->task_state = SLAPI_TASK_FINISHED;
-    slapi_task_status_changed(task);
-
+    slapi_task_finish(task, rv);
     charray_free(pb->pb_db2index_attrs);
     slapi_ch_free((void **)&pb->pb_instance_name);
     slapi_pblock_destroy(pb);
@@ -1353,16 +1611,13 @@
     }
 
     /* allocate new task now */
-    task = new_task(slapi_entry_get_ndn(e));
+    task = slapi_new_task(slapi_entry_get_ndn(e));
     if (task == NULL) {
         LDAPDebug(LDAP_DEBUG_ANY, "unable to allocate new task!\n", 0, 0, 0);
         *returncode = LDAP_OPERATIONS_ERROR;
         rv = SLAPI_DSE_CALLBACK_ERROR;
         goto out;
     }
-    task->task_state = SLAPI_TASK_SETUP;
-    task->task_work = 1;
-    task->task_progress = 0;
 
     mypb = slapi_pblock_new();
     if (mypb == NULL) {
@@ -1375,7 +1630,7 @@
     mypb->pb_instance_name = slapi_ch_strdup(instance_name);
     mypb->pb_db2index_attrs = indexlist;
     mypb->pb_task = task;
-    mypb->pb_task_flags = TASK_RUNNING_AS_TASK;
+    mypb->pb_task_flags = SLAPI_TASK_RUNNING_AS_TASK;
 
     /* start the db2index as a separate thread */
     thread = PR_CreateThread(PR_USER_THREAD, task_index_thread,
@@ -1460,14 +1715,14 @@
     }
 
     /* allocate new task now */
-    task = new_task(slapi_entry_get_ndn(e));
+    task = slapi_new_task(slapi_entry_get_ndn(e));
     if (task == NULL) {
         LDAPDebug(LDAP_DEBUG_ANY, "unable to allocate new task!\n", 0, 0, 0);
         *returncode = LDAP_OPERATIONS_ERROR;
         rv = SLAPI_DSE_CALLBACK_ERROR;
         goto out;
     }
-    task->task_state = SLAPI_TASK_SETUP;
+    /* NGK - This could use some cleanup to use the SLAPI task API, such as slapi_task_begin() */
     task->task_work = 1;
     task->task_progress = 0;
 
@@ -1478,7 +1733,7 @@
         mypb.pb_seq_type = SLAPI_UPGRADEDB_FORCE; /* force; reindex all regardless the dbversion */
     mypb.pb_seq_val = slapi_ch_strdup(archive_dir);
     mypb.pb_task = task;
-    mypb.pb_task_flags = TASK_RUNNING_AS_TASK;
+    mypb.pb_task_flags = SLAPI_TASK_RUNNING_AS_TASK;
 
     rv = (mypb.pb_plugin->plg_upgradedb)(&mypb);
     if (rv == 0) {
@@ -1502,76 +1757,6 @@
     return SLAPI_DSE_CALLBACK_OK;
 }
 
-/* update attributes in the entry under "cn=tasks" to match the current
- * status of the task.
- */
-#define NEXTMOD(_type, _val) do { \
-    modlist[cur].mod_op = LDAP_MOD_REPLACE; \
-    modlist[cur].mod_type = (_type); \
-    modlist[cur].mod_values = (char **)slapi_ch_malloc(2*sizeof(char *)); \
-    modlist[cur].mod_values[0] = (_val); \
-    modlist[cur].mod_values[1] = NULL; \
-    mod[cur] = &modlist[cur]; \
-    cur++; \
-} while (0)
-void slapi_task_status_changed(Slapi_Task *task)
-{
-    LDAPMod modlist[20];
-    LDAPMod *mod[20];
-    int cur = 0, i;
-    char s1[20], s2[20], s3[20];
-
-    if (shutting_down) {
-        /* don't care about task status updates anymore */
-        return;
-    }
-
-    NEXTMOD(TASK_LOG_NAME, task->task_log);
-    NEXTMOD(TASK_STATUS_NAME, task->task_status);
-    sprintf(s1, "%d", task->task_exitcode);
-    sprintf(s2, "%d", task->task_progress);
-    sprintf(s3, "%d", task->task_work);
-    NEXTMOD(TASK_PROGRESS_NAME, s2);
-    NEXTMOD(TASK_WORK_NAME, s3);
-    /* only add the exit code when the job is done */
-    if ((task->task_state == SLAPI_TASK_FINISHED) ||
-        (task->task_state == SLAPI_TASK_CANCELLED)) {
-        NEXTMOD(TASK_EXITCODE_NAME, s1);
-        /* make sure the console can tell the task has ended */
-        if (task->task_progress != task->task_work) {
-            task->task_progress = task->task_work;
-        }
-    }
-
-    mod[cur] = NULL;
-    modify_internal_entry(task->task_dn, mod);
-
-    for (i = 0; i < cur; i++)
-        slapi_ch_free((void **)&modlist[i].mod_values);
-
-    if ((task->task_state == SLAPI_TASK_FINISHED) &&
-        !(task->task_flags & SLAPI_TASK_DESTROYING)) {
-        Slapi_PBlock *pb = slapi_pblock_new();
-        Slapi_Entry *e;
-        int ttl;
-        time_t expire;
-
-        e = get_internal_entry(pb, task->task_dn);
-        if (e == NULL)
-            return;
-        ttl = atoi(fetch_attr(e, "ttl", DEFAULT_TTL));
-        if (ttl > 3600)
-            ttl = 3600;         /* be reasonable. */
-        expire = time(NULL) + ttl;
-        task->task_flags |= SLAPI_TASK_DESTROYING;
-        /* queue an event to destroy the state info */
-        slapi_eq_once(destroy_task, (void *)task, expire);
-
-        slapi_free_search_results_internal(pb);
-        slapi_pblock_destroy(pb);
-    }
-}
-
 /* cleanup old tasks that may still be in the DSE from a previous session
  * (this can happen if the server crashes [no matter how unlikely we like
  * to think that is].)
@@ -1636,84 +1821,6 @@
     slapi_pblock_destroy(pb);
 }
 
-/* name is, for exmaple, "import" */
-int slapi_task_register_handler(const char *name, dseCallbackFn func)
-{
-    char *dn = NULL;
-    Slapi_PBlock *pb = NULL;
-    Slapi_Operation *op;
-    LDAPMod *mods[3];
-    LDAPMod mod[3];
-    const char *objectclass[3];
-    const char *cnvals[2];
-    int ret = -1;
-    int x;
-
-    dn = slapi_ch_smprintf("cn=%s, %s", name, TASK_BASE_DN);
-    if (dn == NULL) {
-        goto out;
-    }
-
-    pb = slapi_pblock_new();
-    if (pb == NULL) {
-        goto out;
-    }
-
-    /* this is painful :( */
-    mods[0] = &mod[0];
-    mod[0].mod_op = LDAP_MOD_ADD;
-    mod[0].mod_type = "objectClass";
-    mod[0].mod_values = (char **)objectclass;
-    objectclass[0] = "top";
-    objectclass[1] = "extensibleObject";
-    objectclass[2] = NULL;
-    mods[1] = &mod[1];
-    mod[1].mod_op = LDAP_MOD_ADD;
-    mod[1].mod_type = "cn";
-    mod[1].mod_values = (char **)cnvals;
-    cnvals[0] = name;
-    cnvals[1] = NULL;
-    mods[2] = NULL;
-    slapi_add_internal_set_pb(pb, dn, mods, NULL,
-                              plugin_get_default_component_id(), 0);
-    x = 1;
-    slapi_pblock_set(pb, SLAPI_DSE_DONT_WRITE_WHEN_ADDING, &x);
-    /* Make sure these adds don't appear in the audit and change logs */
-    slapi_pblock_get(pb, SLAPI_OPERATION, &op);
-    operation_set_flag(op, OP_FLAG_ACTION_NOLOG);
-
-    slapi_add_internal_pb(pb);
-    slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &x);
-    if ((x != LDAP_SUCCESS) && (x != LDAP_ALREADY_EXISTS)) {
-        LDAPDebug(LDAP_DEBUG_ANY,
-                  "Can't create task node '%s' (error %d)\n",
-                  name, x, 0);
-        ret = x;
-        goto out;
-    }
-
-    /* register add callback */
-    slapi_config_register_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP,
-                                   dn, LDAP_SCOPE_SUBTREE, "(objectclass=*)", func, NULL);
-    /* deny modify/delete of the root task entry */
-    slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP,
-                                   dn, LDAP_SCOPE_BASE, "(objectclass=*)", task_deny, NULL);
-    slapi_config_register_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP,
-                                   dn, LDAP_SCOPE_BASE, "(objectclass=*)", task_deny, NULL);
-
-    ret = 0;
-
-out:
-    if (dn) {
-        slapi_ch_free((void **)&dn);
-    }
-    if (pb) {
-        slapi_pblock_destroy(pb);
-    }
-    return ret;
-}
-
-
 void task_init(void)
 {
     global_task_lock = PR_NewLock();




More information about the Fedora-directory-commits mailing list