summaryrefslogtreecommitdiffstats
path: root/ldap/servers/slapd
diff options
context:
space:
mode:
authorNathan Kinder <nkinder@redhat.com>2008-04-03 16:52:47 +0000
committerNathan Kinder <nkinder@redhat.com>2008-04-03 16:52:47 +0000
commit58b91ec4cb2b7b4ede0b9cb48bf54c1ca9c34d78 (patch)
tree9883a74eb0aa1d22f3a80eca26bd55325242eb7e /ldap/servers/slapd
parent49bca93614ca0705d226630288ff8cc73df86674 (diff)
downloadds-58b91ec4cb2b7b4ede0b9cb48bf54c1ca9c34d78.tar.gz
ds-58b91ec4cb2b7b4ede0b9cb48bf54c1ca9c34d78.tar.xz
ds-58b91ec4cb2b7b4ede0b9cb48bf54c1ca9c34d78.zip
Resolves: 439907
Summary: Enhanced SLAPI task API and ported existing tasks to use new API.
Diffstat (limited to 'ldap/servers/slapd')
-rw-r--r--ldap/servers/slapd/back-ldbm/archive.c4
-rw-r--r--ldap/servers/slapd/back-ldbm/back-ldbm.h6
-rw-r--r--ldap/servers/slapd/back-ldbm/dblayer.c6
-rw-r--r--ldap/servers/slapd/back-ldbm/import.c52
-rw-r--r--ldap/servers/slapd/back-ldbm/ldif2ldbm.c20
-rw-r--r--ldap/servers/slapd/main.c14
-rw-r--r--ldap/servers/slapd/slap.h25
-rw-r--r--ldap/servers/slapd/slapi-plugin.h37
-rw-r--r--ldap/servers/slapd/slapi-private.h40
-rw-r--r--ldap/servers/slapd/task.c749
-rw-r--r--ldap/servers/slapd/test-plugins/sampletask.c115
11 files changed, 583 insertions, 485 deletions
diff --git a/ldap/servers/slapd/back-ldbm/archive.c b/ldap/servers/slapd/back-ldbm/archive.c
index be2c4c63..a0568b7a 100644
--- a/ldap/servers/slapd/back-ldbm/archive.c
+++ b/ldap/servers/slapd/back-ldbm/archive.c
@@ -61,7 +61,7 @@ int ldbm_back_archive2ldbm( Slapi_PBlock *pb )
slapi_pblock_get( pb, SLAPI_BACKEND_INSTANCE_NAME, &backendname);
slapi_pblock_get( pb, SLAPI_BACKEND_TASK, &task );
slapi_pblock_get( pb, SLAPI_TASK_FLAGS, &task_flags );
- li->li_flags = run_from_cmdline = (task_flags & TASK_RUNNING_FROM_COMMANDLINE);
+ li->li_flags = run_from_cmdline = (task_flags & SLAPI_TASK_RUNNING_FROM_COMMANDLINE);
if ( !rawdirectory || !*rawdirectory ) {
LDAPDebug( LDAP_DEBUG_ANY, "archive2db: no archive name\n",
@@ -273,7 +273,7 @@ int ldbm_back_ldbm2archive( Slapi_PBlock *pb )
slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
slapi_pblock_get( pb, SLAPI_SEQ_VAL, &rawdirectory );
slapi_pblock_get( pb, SLAPI_TASK_FLAGS, &task_flags );
- li->li_flags = run_from_cmdline = (task_flags & TASK_RUNNING_FROM_COMMANDLINE);
+ li->li_flags = run_from_cmdline = (task_flags & SLAPI_TASK_RUNNING_FROM_COMMANDLINE);
slapi_pblock_get( pb, SLAPI_BACKEND_TASK, &task );
diff --git a/ldap/servers/slapd/back-ldbm/back-ldbm.h b/ldap/servers/slapd/back-ldbm/back-ldbm.h
index 87e04683..2af305fe 100644
--- a/ldap/servers/slapd/back-ldbm/back-ldbm.h
+++ b/ldap/servers/slapd/back-ldbm/back-ldbm.h
@@ -513,10 +513,10 @@ struct ldbminfo {
int li_legacy_errcode; /* 615428 -- in case legacy err code is expected */
};
-/* li_flags could store these bits defined in ../slap.h
+/* li_flags could store these bits defined in ../slapi-plugin.h
* task flag (pb_task_flags) *
- * #define TASK_RUNNING_AS_TASK 0x0
- * #define TASK_RUNNING_FROM_COMMANDLINE 0x1
+ * SLAPI_TASK_RUNNING_AS_TASK
+ * SLAPI_TASK_RUNNING_FROM_COMMANDLINE
*/
/* allow conf w/o CONFIG_FLAG_ALLOW_RUNNING_CHANGE to be updated */
#define LI_FORCE_MOD_CONFIG 0x10
diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c
index 8f0bc07b..abd71b85 100644
--- a/ldap/servers/slapd/back-ldbm/dblayer.c
+++ b/ldap/servers/slapd/back-ldbm/dblayer.c
@@ -1954,7 +1954,7 @@ int dblayer_instance_start(backend *be, int mode)
oflags |= DB_PRIVATE;
}
PR_Lock(li->li_config_mutex);
- if ((li->li_flags & TASK_RUNNING_FROM_COMMANDLINE) &&
+ if ((li->li_flags & SLAPI_TASK_RUNNING_FROM_COMMANDLINE) &&
(li->li_import_cache_autosize)) /* Autosizing importCache
* Need to re-eval every time
* to guarantee the memory is
@@ -5678,7 +5678,7 @@ int dblayer_restore(struct ldbminfo *li, char *src_dir, Slapi_Task *task, char *
* dse_conf_verify may need to have db started, as well. */
/* If no logfiles were stored, then fatal recovery isn't required */
- if (li->li_flags & TASK_RUNNING_FROM_COMMANDLINE)
+ if (li->li_flags & SLAPI_TASK_RUNNING_FROM_COMMANDLINE)
{
/* command line mode; no need to run db threads */
dbmode |= DBLAYER_NO_DBTHREADS_MODE;
@@ -5707,7 +5707,7 @@ int dblayer_restore(struct ldbminfo *li, char *src_dir, Slapi_Task *task, char *
"Warning: Unable to verify the index configuration\n", 0, 0, 0);
}
- if (li->li_flags & TASK_RUNNING_FROM_COMMANDLINE) {
+ if (li->li_flags & SLAPI_TASK_RUNNING_FROM_COMMANDLINE) {
/* command line: close the database down again */
tmp_rval = dblayer_close(li, dbmode);
if (0 != tmp_rval) {
diff --git a/ldap/servers/slapd/back-ldbm/import.c b/ldap/servers/slapd/back-ldbm/import.c
index 7666dcfe..533a61c3 100644
--- a/ldap/servers/slapd/back-ldbm/import.c
+++ b/ldap/servers/slapd/back-ldbm/import.c
@@ -197,29 +197,19 @@ void import_log_notice(ImportJob *job, char *format, ...)
buffer, 0);
}
-static int import_task_destroy(Slapi_Task *task)
+static void import_task_destroy(Slapi_Task *task)
{
- ImportJob *job = (ImportJob *)task->task_private;
-
- if (task->task_log) {
- slapi_ch_free((void **)&task->task_log);
- }
-
- if (task->task_status) {
- slapi_ch_free((void **)&task->task_status);
- }
-
+ ImportJob *job = (ImportJob *)slapi_task_get_data(task);
if (job && job->task_status) {
slapi_ch_free((void **)&job->task_status);
job->task_status = NULL;
}
FREE(job);
- task->task_private = NULL;
- return 0;
+ slapi_task_set_data(task, NULL);
}
-static int import_task_abort(Slapi_Task *task)
+static void import_task_abort(Slapi_Task *task)
{
ImportJob *job;
@@ -227,9 +217,8 @@ static int import_task_abort(Slapi_Task *task)
* DSE lock for modify...
*/
- if (task->task_state == SLAPI_TASK_FINISHED) {
+ if (slapi_task_get_state(task) == SLAPI_TASK_FINISHED) {
/* too late */
- return 0;
}
/*
@@ -238,14 +227,12 @@ static int import_task_abort(Slapi_Task *task)
* because it will free the job.
*/
- job = (ImportJob *)task->task_private;
+ job = (ImportJob *)slapi_task_get_data(task);
import_abort_all(job, 0);
- while (task->task_state != SLAPI_TASK_FINISHED)
+ while (slapi_task_get_state(task) != SLAPI_TASK_FINISHED)
DS_Sleep(PR_MillisecondsToInterval(100));
-
- return 0;
}
@@ -1042,13 +1029,8 @@ static int import_all_done(ImportJob *job, int ret)
slapi_ch_free_string(&inst_dirp);
}
- if (job->task != NULL && 0 == job->task->task_refcount) {
- /* exit code */
- job->task->task_exitcode = ret;
- job->task->task_state = SLAPI_TASK_FINISHED;
- job->task->task_progress = job->task->task_work;
- job->task->task_private = NULL;
- slapi_task_status_changed(job->task);
+ if ((job->task != NULL) && (0 == slapi_task_get_refcount(job->task))) {
+ slapi_task_finish(job->task, ret);
}
if (job->flags & FLAG_ONLINE) {
@@ -1093,7 +1075,7 @@ int import_main_offline(void *arg)
ImportWorkerInfo *producer = NULL;
if (job->task)
- job->task->task_refcount++;
+ slapi_task_inc_refcount(job->task);
PR_ASSERT(inst != NULL);
time(&beginning);
@@ -1364,13 +1346,11 @@ error:
if (0 != ret) {
import_log_notice(job, "Import failed.");
if (job->task != NULL) {
- job->task->task_state = SLAPI_TASK_FINISHED;
- job->task->task_exitcode = ret;
- slapi_task_status_changed(job->task);
+ slapi_task_finish(job->task, ret);
}
} else {
if (job->task)
- job->task->task_refcount--;
+ slapi_task_dec_refcount(job->task);
import_all_done(job, ret);
}
@@ -1471,15 +1451,17 @@ int ldbm_back_ldif2ldbm_deluxe(Slapi_PBlock *pb)
/* add 1 to account for post-import cleanup (which can take a
* significant amount of time)
*/
+ /* NGK - This should eventually be cleaned up to use the public
+ * task API. */
if (0 == total_files) /* reindexing */
job->task->task_work = 2;
else
job->task->task_work = total_files + 1;
job->task->task_progress = 0;
job->task->task_state = SLAPI_TASK_RUNNING;
- job->task->task_private = job;
- job->task->destructor = import_task_destroy;
- job->task->cancel = import_task_abort;
+ slapi_task_set_data(job->task, job);
+ slapi_task_set_destructor_fn(job->task, import_task_destroy);
+ slapi_task_set_cancel_fn(job->task, import_task_abort);
job->flags |= FLAG_ONLINE;
/* create thread for import_main, so we can return */
diff --git a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
index 827e471c..e4f82b2f 100644
--- a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
+++ b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
@@ -568,7 +568,7 @@ int ldbm_back_ldif2ldbm( Slapi_PBlock *pb )
/* hopefully this will go away once import is not run standalone... */
slapi_pblock_get(pb, SLAPI_TASK_FLAGS, &task_flags);
- if (task_flags & TASK_RUNNING_FROM_COMMANDLINE) {
+ if (task_flags & SLAPI_TASK_RUNNING_FROM_COMMANDLINE) {
/* initialize UniqueID generator - must be done once backends are started
and event queue is initialized but before plugins are started */
Slapi_DN *sdn = slapi_sdn_new_dn_byval ("cn=uniqueid generator,cn=config");
@@ -581,7 +581,7 @@ int ldbm_back_ldif2ldbm( Slapi_PBlock *pb )
return -1;
}
- li->li_flags |= TASK_RUNNING_FROM_COMMANDLINE;
+ li->li_flags |= SLAPI_TASK_RUNNING_FROM_COMMANDLINE;
ldbm_config_load_dse_info(li);
autosize_import_cache(li);
}
@@ -604,7 +604,7 @@ int ldbm_back_ldif2ldbm( Slapi_PBlock *pb )
/***** prepare & init libdb and dblayer *****/
- if (! (task_flags & TASK_RUNNING_FROM_COMMANDLINE)) {
+ if (! (task_flags & SLAPI_TASK_RUNNING_FROM_COMMANDLINE)) {
/* shutdown this instance of the db */
LDAPDebug(LDAP_DEBUG_ANY, "Bringing %s offline...\n",
instance_name, 0, 0);
@@ -778,11 +778,11 @@ ldbm_back_ldbm2ldif( Slapi_PBlock *pb )
slapi_pblock_get( pb, SLAPI_TASK_FLAGS, &task_flags );
slapi_pblock_get( pb, SLAPI_DB2LDIF_DECRYPT, &decrypt );
slapi_pblock_get( pb, SLAPI_DB2LDIF_SERVER_RUNNING, &server_running );
- run_from_cmdline = (task_flags & TASK_RUNNING_FROM_COMMANDLINE);
+ run_from_cmdline = (task_flags & SLAPI_TASK_RUNNING_FROM_COMMANDLINE);
dump_replica = pb->pb_ldif_dump_replica;
if (run_from_cmdline) {
- li->li_flags |= TASK_RUNNING_FROM_COMMANDLINE;
+ li->li_flags |= SLAPI_TASK_RUNNING_FROM_COMMANDLINE;
if (!dump_replica) {
we_start_the_backends = 1;
}
@@ -1298,12 +1298,12 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb)
slapi_pblock_get(pb, SLAPI_BACKEND_INSTANCE_NAME, &instance_name);
slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &li);
slapi_pblock_get(pb, SLAPI_TASK_FLAGS, &task_flags);
- run_from_cmdline = (task_flags & TASK_RUNNING_FROM_COMMANDLINE);
+ run_from_cmdline = (task_flags & SLAPI_TASK_RUNNING_FROM_COMMANDLINE);
slapi_pblock_get(pb, SLAPI_BACKEND_TASK, &task);
if (run_from_cmdline) {
/* No ldbm backend exists until we process the config info. */
- li->li_flags |= TASK_RUNNING_FROM_COMMANDLINE;
+ li->li_flags |= SLAPI_TASK_RUNNING_FROM_COMMANDLINE;
ldbm_config_load_dse_info(li);
txn.back_txn_txn = NULL; /* no transaction */
}
@@ -1764,6 +1764,8 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb)
percent = (ep->ep_id*100 / (lastid ? lastid : 1));
}
if (task) {
+ /* NGK - This should eventually be cleaned up to use the
+ * public task API */
task->task_progress = (idl ? idindex : ep->ep_id);
task->task_work = (idl ? idl->b_nids : lastid);
slapi_task_status_changed(task);
@@ -1970,7 +1972,7 @@ int ldbm_back_upgradedb(Slapi_PBlock *pb)
slapi_pblock_get(pb, SLAPI_BACKEND_TASK, &task);
slapi_pblock_get(pb, SLAPI_DB2LDIF_SERVER_RUNNING, &server_running);
- run_from_cmdline = (task_flags & TASK_RUNNING_FROM_COMMANDLINE);
+ run_from_cmdline = (task_flags & SLAPI_TASK_RUNNING_FROM_COMMANDLINE);
slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &li);
if (run_from_cmdline)
{
@@ -2435,7 +2437,7 @@ void upgradedb_core(Slapi_PBlock *pb, ldbm_instance *inst)
int run_from_cmdline = 0;
slapi_pblock_get(pb, SLAPI_TASK_FLAGS, &task_flags);
- run_from_cmdline = (task_flags & TASK_RUNNING_FROM_COMMANDLINE);
+ run_from_cmdline = (task_flags & SLAPI_TASK_RUNNING_FROM_COMMANDLINE);
be = inst->inst_be;
slapi_log_error(SLAPI_LOG_FATAL, "upgrade DB",
diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c
index 0b5f3e7d..1c1943a6 100644
--- a/ldap/servers/slapd/main.c
+++ b/ldap/servers/slapd/main.c
@@ -2118,7 +2118,7 @@ slapd_exemode_ldif2db()
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 @@ slapd_exemode_db2ldif(int argc, char** argv)
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 @@ static int slapd_exemode_db2index()
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 @@ slapd_exemode_db2archive()
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 @@ slapd_exemode_archive2db()
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 @@ slapd_exemode_upgradedb()
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 @@ slapd_exemode_dbverify()
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 );
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index f1777eb8..0b3305e3 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1283,6 +1283,27 @@ typedef struct conn {
#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 @@ extern char *attr_dataversion;
#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
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index f963621e..b7f5f927 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -149,9 +149,10 @@ typedef struct slapi_rdn Slapi_RDN;
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 @@ void slapi_register_role_check(roles_check_fn_type check_fn);
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 @@ typedef int (*dseCallbackFn)(Slapi_PBlock *, Slapi_Entry *, Slapi_Entry *,
#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__
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
index 834ce46d..1225e8d5 100644
--- a/ldap/servers/slapd/slapi-private.h
+++ b/ldap/servers/slapd/slapi-private.h
@@ -1060,22 +1060,6 @@ int slapi_uniqueIDGenerateFromNameString(char **uId,
*/
/*
- * 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 @@ int slapd_re_init( void );
/***** 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 */
diff --git a/ldap/servers/slapd/task.c b/ldap/servers/slapd/task.c
index 13606c1c..67c93c16 100644
--- a/ldap/servers/slapd/task.c
+++ b/ldap/servers/slapd/task.c
@@ -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 Slapi_Task *global_task_list = NULL;
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 @@ static int shutting_down = 0;
#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 @@ new_task(const char *dn)
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 @@ new_task(const char *dn)
/* 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 @@ destroy_task(time_t when, void *arg)
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) {
@@ -152,35 +551,6 @@ destroy_task(time_t when, void *arg)
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);
-}
-
-/********** some useful helper functions **********/
-
-
/* 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).
* you do not need to free anything returned by this.
@@ -268,81 +638,7 @@ static void modify_internal_entry(char *dn, LDAPMod **mods)
} 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 @@ static int task_generic_destructor(Slapi_Task *task)
slapi_ch_free((void **)&task->task_status);
}
task->task_log = task->task_status = NULL;
- return 0;
}
@@ -553,13 +848,12 @@ static int task_import_add(Slapi_PBlock *pb, Slapi_Entry *e,
}
/* 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 @@ static int task_import_add(Slapi_PBlock *pb, Slapi_Entry *e,
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 @@ static void task_export_thread(void *arg)
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 @@ static void task_export_thread(void *arg)
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 @@ static void task_export_thread(void *arg)
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 @@ static int task_export_add(Slapi_PBlock *pb, Slapi_Entry *e,
}
/* 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 @@ static int task_export_add(Slapi_PBlock *pb, Slapi_Entry *e,
/* 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 @@ static void task_backup_thread(void *arg)
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 @@ static void task_backup_thread(void *arg)
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 @@ static int task_backup_add(Slapi_PBlock *pb, Slapi_Entry *e,
}
/* 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 @@ static int task_backup_add(Slapi_PBlock *pb, Slapi_Entry *e,
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 @@ static void task_restore_thread(void *arg)
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 @@ static void task_restore_thread(void *arg)
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 @@ static int task_restore_add(Slapi_PBlock *pb, Slapi_Entry *e,
}
/* 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 @@ static int task_restore_add(Slapi_PBlock *pb, Slapi_Entry *e,
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 @@ static void task_index_thread(void *arg)
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 @@ static void task_index_thread(void *arg)
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 @@ static int task_index_add(Slapi_PBlock *pb, Slapi_Entry *e,
}
/* 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 @@ static int task_index_add(Slapi_PBlock *pb, Slapi_Entry *e,
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 @@ task_upgradedb_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
}
/* 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 @@ task_upgradedb_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
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 @@ out:
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 @@ void task_cleanup(void)
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();
diff --git a/ldap/servers/slapd/test-plugins/sampletask.c b/ldap/servers/slapd/test-plugins/sampletask.c
index 94f1ade8..357ed5ca 100644
--- a/ldap/servers/slapd/test-plugins/sampletask.c
+++ b/ldap/servers/slapd/test-plugins/sampletask.c
@@ -47,7 +47,7 @@
* objectClass: nsSlapdPlugin
* objectClass: extensibleObject
* cn: sampletask
- * nsslapd-pluginPath: <prefix>/usr/lib/<PACKAGE_NAME>/plugins/libsampletask-plugin.so
+ * nsslapd-pluginPath: libsampletask-plugin
* nsslapd-pluginInitfunc: sampletask_init
* nsslapd-pluginType: object
* nsslapd-pluginEnabled: on
@@ -58,26 +58,26 @@
*
* 4. create a config task entry in dse.ldif
* Task entry:
- * dn: cn=sample task, cn=tasks, cn=config
+ * dn: cn=sampletask, cn=tasks, cn=config
* objectClass: top
* objectClass: extensibleObject
- * cn: sample task
+ * cn: sampletask
*
* 5. to invoke the sample task, run the command line:
* $ ./ldapmodify -h <host> -p <port> -D "cn=Directory Manager" -w <pw> -a
- * dn: cn=sample task 0, cn=sample task, cn=tasks, cn=config
+ * dn: cn=sampletask 0, cn=sample task, cn=tasks, cn=config
* objectClass: top
* objectClass: extensibleObject
* cn: sample task 0
- * arg0: sample task arg0
+ * myarg: sample task myarg
*
* Result is in the errors log
- * [...] - Sample task starts (arg: sample task arg0) ...
+ * [...] - Sample task starts (arg: sample task myarg) ...
* [...] - Sample task finished.
*/
-#include "slap.h"
-#include "slapi-private.h"
+#include "slapi-plugin.h"
+#include "nspr.h"
static int task_sampletask_add(Slapi_PBlock *pb, Slapi_Entry *e,
Slapi_Entry *eAfter, int *returncode, char *returntext,
@@ -118,33 +118,32 @@ task_sampletask_start(Slapi_PBlock *pb)
static void
task_sampletask_thread(void *arg)
{
- Slapi_PBlock *pb = (Slapi_PBlock *)arg;
- Slapi_Task *task = pb->pb_task;
- int rv;
-
- task->task_work = 1;
- task->task_progress = 0;
- task->task_state = SLAPI_TASK_RUNNING;
- slapi_task_status_changed(task);
-
- slapi_task_log_notice(task, "Sample task starts (arg: %s) ...\n",
- pb->pb_seq_val);
- LDAPDebug(LDAP_DEBUG_ANY, "Sample task starts (arg: %s) ...\n",
- pb->pb_seq_val, 0, 0);
- /* do real work */
- rv = 0;
+ Slapi_Task *task = (Slapi_Task *)arg;
+ char *myarg = NULL;
+ int i, rv = 0;
+ int total_work = 3;
+
+ /* fetch our argument from the task */
+ myarg = (char *)slapi_task_get_data(task);
+
+ /* update task state to show it's running */
+ slapi_task_begin(task, total_work);
+ slapi_task_log_notice(task, "Sample task starts (arg: %s) ...\n", myarg);
+ slapi_log_error(SLAPI_LOG_FATAL, "sampletask", "Sample task starts (arg: %s) ...\n", myarg);
+
+ /* real work would be done here */
+ for (i = 0; i < total_work; i++) {
+ PR_Sleep(10000);
+ slapi_task_inc_progress(task);
+ }
+ /* update task state to say we're finished */
slapi_task_log_notice(task, "Sample task finished.");
slapi_task_log_status(task, "Sample task finished.");
- LDAPDebug(LDAP_DEBUG_ANY, "Sample task 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_log_error(SLAPI_LOG_FATAL, "sampletask", "Sample task finished.\n");
- slapi_ch_free((void **)&pb->pb_seq_val);
- slapi_pblock_destroy(pb);
+ /* this will queue the destruction of the task */
+ slapi_task_finish(task, rv);
}
/* extract a single value from the entry (as a string) -- if it's not in the
@@ -163,6 +162,17 @@ static const char *fetch_attr(Slapi_Entry *e, const char *attrname,
return slapi_value_get_string(val);
}
+static void
+task_sampletask_destructor(Slapi_Task *task)
+{
+ if (task) {
+ char *myarg = (char *)slapi_task_get_data(task);
+ if (myarg) {
+ slapi_ch_free_string(&myarg);
+ }
+ }
+}
+
/*
* Invoked when the task instance is added by the client (step 5 of the comment)
* Get the necessary attributes from the task entry, and spawns a thread to do
@@ -178,7 +188,7 @@ task_sampletask_add(Slapi_PBlock *pb, Slapi_Entry *e,
int rv = SLAPI_DSE_CALLBACK_OK;
Slapi_PBlock *mypb = NULL;
Slapi_Task *task = NULL;
- const char *arg0;
+ const char *myarg;
*returncode = LDAP_SUCCESS;
if ((cn = fetch_attr(e, "cn", NULL)) == NULL) {
@@ -188,7 +198,7 @@ task_sampletask_add(Slapi_PBlock *pb, Slapi_Entry *e,
}
/* get arg(s) */
- if ((arg0 = fetch_attr(e, "arg0", NULL)) == NULL) {
+ if ((myarg = fetch_attr(e, "myarg", NULL)) == NULL) {
*returncode = LDAP_OBJECT_CLASS_VIOLATION;
rv = SLAPI_DSE_CALLBACK_ERROR;
goto out;
@@ -197,46 +207,33 @@ task_sampletask_add(Slapi_PBlock *pb, Slapi_Entry *e,
/* allocate new task now */
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);
+ slapi_log_error(SLAPI_LOG_FATAL, "sampletask", "unable to allocate new task!\n");
*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;
- /* create a pblock to pass the necessary info to the task thread */
- mypb = slapi_pblock_new();
- if (mypb == NULL) {
- *returncode = LDAP_OPERATIONS_ERROR;
- rv = SLAPI_DSE_CALLBACK_ERROR;
- goto out;
- }
- mypb->pb_seq_val = slapi_ch_strdup(arg0);
- mypb->pb_task = task;
- mypb->pb_task_flags = TASK_RUNNING_AS_TASK;
+ /* set a destructor that will clean up myarg for us when the task is complete */
+ slapi_task_set_destructor_fn(task, task_sampletask_destructor);
+
+ /* Stash our argument in the task for use by the task thread */
+ slapi_task_set_data(task, slapi_ch_strdup(myarg));
/* start the sample task as a separate thread */
thread = PR_CreateThread(PR_USER_THREAD, task_sampletask_thread,
- (void *)mypb, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ (void *)task, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
if (thread == NULL) {
- LDAPDebug(LDAP_DEBUG_ANY,
- "unable to create sample task thread!\n", 0, 0, 0);
+ slapi_log_error(SLAPI_LOG_FATAL, "sampletask",
+ "unable to create sample task thread!\n");
*returncode = LDAP_OPERATIONS_ERROR;
rv = SLAPI_DSE_CALLBACK_ERROR;
- slapi_ch_free((void **)&mypb->pb_seq_val);
- slapi_pblock_destroy(mypb);
- goto out;
+ slapi_task_finish(task, *returncode);
+ } else {
+ /* thread successful */
+ rv = SLAPI_DSE_CALLBACK_OK;
}
- /* thread successful -- don't free the pb, let the thread do that. */
- return SLAPI_DSE_CALLBACK_OK;
-
out:
- if (task) {
- slapi_destroy_task(task);
- }
return rv;
}