Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
include/qb/qbloop.h | 20 ++++++++++++++++++++
lib/loop_job.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
lib/loop_poll.c | 2 +-
tests/check_loop.c | 44 +++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 112 insertions(+), 2 deletions(-)
diff --git a/include/qb/qbloop.h b/include/qb/qbloop.h
index b2afecc..e482e29 100644
--- a/include/qb/qbloop.h
+++ b/include/qb/qbloop.h
@@ -107,6 +107,26 @@ int32_t qb_loop_job_add(qb_loop_t *l,
void *data,
qb_loop_job_dispatch_fn dispatch_fn);
+
+/**
+ * Delete a job from the mainloop.
+ *
+ * This will try to delete the job if it hasn't run yet.
+ *
+ * @note this will remove the first job that matches the
+ * paramaters (priority, data, dispatch_fn).
+ *
+ * @param l pointer to the loop instance
+ * @param p the priority
+ * @param data user data passed into the dispatch function
+ * @param dispatch_fn callback function
+ * @return status (0 == ok, -errno == failure)
+ */
+int32_t qb_loop_job_del(struct qb_loop *lp,
+ enum qb_loop_priority p,
+ void *data,
+ qb_loop_job_dispatch_fn dispatch_fn);
+
/**
* Add a timer to the mainloop.
* @note it is a one-shot job.
diff --git a/lib/loop_job.c b/lib/loop_job.c
index 3f261f2..23b3eb6 100644
--- a/lib/loop_job.c
+++ b/lib/loop_job.c
@@ -24,6 +24,7 @@
#include <qb/qblist.h>
#include <qb/qbloop.h>
#include "loop_int.h"
+#include "util_int.h"
struct qb_loop_job {
struct qb_loop_item item;
@@ -118,3 +119,50 @@ qb_loop_job_add(struct qb_loop *lp,
return 0;
}
+
+int32_t
+qb_loop_job_del(struct qb_loop *lp,
+ enum qb_loop_priority p,
+ void *data, qb_loop_job_dispatch_fn dispatch_fn)
+{
+ struct qb_loop_job *job;
+ struct qb_loop_item *item;
+ struct qb_loop *l = lp;
+
+ if (l == NULL) {
+ l = qb_loop_default_get();
+ }
+ if (l == NULL || dispatch_fn == NULL) {
+ return -EINVAL;
+ }
+ if (p > QB_LOOP_HIGH) {
+ return -EINVAL;
+ }
+
+ qb_list_for_each_entry(item, &l->level[p].wait_head, list) {
+ job = (struct qb_loop_job *)item;
+ if (job->dispatch_fn == dispatch_fn &&
+ job->item.user_data == data &&
+ job->item.type == QB_LOOP_JOB) {
+ qb_list_del(&job->item.list);
+ free(job);
+ return 0;
+ }
+ }
+
+ qb_list_for_each_entry(item, &l->level[p].job_head, list) {
+
+ if (item->type != QB_LOOP_JOB) {
+ continue;
+ }
+ job = (struct qb_loop_job *)item;
+ if (job->dispatch_fn == dispatch_fn &&
+ job->item.user_data == data) {
+ qb_loop_level_item_del(&l->level[p], item);
+ qb_util_log(LOG_DEBUG, "deleting job in JOBLIST");
+ return 0;
+ }
+ }
+
+ return -ENOENT;
+}
diff --git a/lib/loop_poll.c b/lib/loop_poll.c
index e379ebf..2f6fc20 100644
--- a/lib/loop_poll.c
+++ b/lib/loop_poll.c
@@ -819,7 +819,7 @@ qb_loop_timer_del(struct qb_loop * lp, qb_loop_timer_handle th)
}
if (pe->state == QB_POLL_ENTRY_JOBLIST) {
qb_loop_level_item_del(&l->level[pe->p], &pe->item);
- qb_util_log(LOG_DEBUG, "trying to delete timer in JOBLIST");
+ qb_util_log(LOG_DEBUG, "deleting timer in JOBLIST");
}
if (pe->state != QB_POLL_ENTRY_ACTIVE &&
pe->state != QB_POLL_ENTRY_JOBLIST) {
diff --git a/tests/check_loop.c b/tests/check_loop.c
index 3090faf..8bd862c 100644
--- a/tests/check_loop.c
+++ b/tests/check_loop.c
@@ -221,6 +221,44 @@ START_TEST(test_job_rate_limit)
}
END_TEST
+static void job_stop_and_del_1(void *data)
+{
+ int32_t res;
+ qb_loop_t *l = (qb_loop_t *)data;
+ job_3_run_count++;
+ res = qb_loop_job_del(l, QB_LOOP_MED, l, job_1);
+ ck_assert_int_eq(res, 0);
+ qb_loop_stop(l);
+}
+
+START_TEST(test_job_add_del)
+{
+ int32_t res;
+ qb_loop_t *l = qb_loop_create();
+ fail_if(l == NULL);
+
+ res = qb_loop_job_add(l, QB_LOOP_MED, l, job_1);
+ ck_assert_int_eq(res, 0);
+ res = qb_loop_job_del(l, QB_LOOP_MED, l, job_1);
+ ck_assert_int_eq(res, 0);
+
+ job_1_run_count = 0;
+ job_3_run_count = 0;
+
+ res = qb_loop_job_add(l, QB_LOOP_MED, l, job_1);
+ ck_assert_int_eq(res, 0);
+ res = qb_loop_job_add(l, QB_LOOP_HIGH, l, job_stop_and_del_1);
+ ck_assert_int_eq(res, 0);
+
+ qb_loop_run(l);
+ ck_assert_int_eq(job_1_run_count, 0);
+ ck_assert_int_eq(job_3_run_count, 1);
+
+ qb_loop_destroy(l);
+}
+END_TEST
+
+
static Suite *loop_job_suite(void)
{
TCase *tc;
@@ -248,6 +286,10 @@ static Suite *loop_job_suite(void)
tcase_set_timeout(tc, 5);
suite_add_tcase(s, tc);
+ tc = tcase_create("add_del");
+ tcase_add_test(tc, test_job_add_del);
+ suite_add_tcase(s, tc);
+
return s;
}
@@ -553,7 +595,7 @@ int32_t main(void)
qb_log_init("check", LOG_USER, LOG_EMERG);
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
- QB_LOG_FILTER_FILE, "*", LOG_INFO);
+ QB_LOG_FILTER_FILE, "*", LOG_DEBUG);
qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
srunner_run_all(sr, CK_VERBOSE);
--
1.7.7.6