From 53eb5c1784c76efc3b0fde46427afb75ab4fe5d1 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Thu, 2 Feb 2023 10:10:03 +0100 Subject: [PATCH 01/11] feat(job-queue): first draft of job struct --- include/vieter_job_queue.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 include/vieter_job_queue.h diff --git a/include/vieter_job_queue.h b/include/vieter_job_queue.h new file mode 100644 index 0000000..6c21da0 --- /dev/null +++ b/include/vieter_job_queue.h @@ -0,0 +1,32 @@ +#ifndef VIETER_JOB_QUEUE +#define VIETER_JOB_QUEUE + +#include +#include +#include "vieter_cron.h" + +/* + * The order of these do not imply that they happen in this order. New states + * will just get added as consecutive numbers. Their values should be + * monotonically increasing values, as these will be used to index arrays, among + * other things. + */ +typedef enum vieter_job_state { + vieter_job_queued = 0, + vieter_job_dispatched = 1, + vieter_job_finished = 2 +} vieter_job_state; + +// This macro should be kept in sync with the above enum +#define VIETER_JOB_STATES 3 + +typedef struct vieter_job { + int id; + uint64_t next_scheduled_time; + vieter_cron_expression *ce; + bool single; + vieter_job_state state; + uint64_t state_transition_times[VIETER_JOB_STATES]; +} vieter_job; + +#endif -- 2.40.1 From 8668148e96188540c0e547c51461756f230a9445 Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Thu, 2 Feb 2023 16:14:26 +0100 Subject: [PATCH 02/11] chore: format internal header files --- .editorconfig | 5 ++++ Makefile | 7 +++--- include/vieter_job_queue.h | 30 ++++++++++++++--------- src/job-queue/vieter_job_queue_internal.h | 10 ++++++++ 4 files changed, 38 insertions(+), 14 deletions(-) create mode 100644 .editorconfig create mode 100644 src/job-queue/vieter_job_queue_internal.h diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..a2eb55d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,5 @@ +root = true + +[*.{c,h}] +indent_style = space +indent_size = 2 diff --git a/Makefile b/Makefile index fadf89d..9db32d4 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,8 @@ INC_DIRS ?= include LIB := $(BUILD_DIR)/$(LIB_FILENAME) SRCS != find '$(SRC_DIR)' -iname '*.c' -SRCS_H != find $(INC_DIRS) '$(SRC_DIR)' -iname '*.h' +SRCS_H != find $(INC_DIRS) -iname '*.h' +SRCS_H_INTERNAL != find $(SRC_DIR) -iname '*.h' SRCS_TEST != find '$(TEST_DIR)' -iname '*.c' OBJS := $(SRCS:%=$(BUILD_DIR)/%.o) @@ -86,11 +87,11 @@ $(BUILD_DIR)/$(TEST_DIR)/%.c.o: $(TEST_DIR)/%.c # =====MAINTENANCE===== .PHONY: lint lint: - clang-format -n --Werror $(SRCS) $(SRCS_H) + clang-format -n --Werror $(SRCS) $(SRCS_H) $(SRCS_H_INTERNAL) .PHONY: fmt fmt: - clang-format -i $(SRCS) $(SRCS_H) + clang-format -i $(SRCS) $(SRCS_H) $(SRCS_H_INTERNAL) .PHONY: clean clean: diff --git a/include/vieter_job_queue.h b/include/vieter_job_queue.h index 6c21da0..fc02d7e 100644 --- a/include/vieter_job_queue.h +++ b/include/vieter_job_queue.h @@ -1,9 +1,9 @@ #ifndef VIETER_JOB_QUEUE #define VIETER_JOB_QUEUE -#include -#include #include "vieter_cron.h" +#include +#include /* * The order of these do not imply that they happen in this order. New states @@ -12,21 +12,29 @@ * other things. */ typedef enum vieter_job_state { - vieter_job_queued = 0, - vieter_job_dispatched = 1, - vieter_job_finished = 2 + vieter_job_state_queued = 0, + vieter_job_state_ready = 1, + vieter_job_state_build_finished = 2 } vieter_job_state; // This macro should be kept in sync with the above enum #define VIETER_JOB_STATES 3 typedef struct vieter_job { - int id; - uint64_t next_scheduled_time; - vieter_cron_expression *ce; - bool single; - vieter_job_state state; - uint64_t state_transition_times[VIETER_JOB_STATES]; + int id; + uint64_t next_scheduled_time; + vieter_cron_expression *ce; + bool single; + vieter_job_state state; + uint64_t state_transition_times[VIETER_JOB_STATES]; + bool dispatched; + void *build_config; } vieter_job; +typedef struct vieter_job_queue vieter_job_queue; + +vieter_job_queue *vieter_job_queue_init(); + +void vieter_job_queue_insert(int id); + #endif diff --git a/src/job-queue/vieter_job_queue_internal.h b/src/job-queue/vieter_job_queue_internal.h new file mode 100644 index 0000000..8d8ffc4 --- /dev/null +++ b/src/job-queue/vieter_job_queue_internal.h @@ -0,0 +1,10 @@ +#ifndef VIETER_JOB_QUEUE_INTERNAL +#define VIETER_JOB_QUEUE_INTERNAL + +#include "vieter_tree.h" + +struct vieter_job_queue { + vieter_tree *tree; +}; + +#endif -- 2.40.1 From 02bd2c24b72b91eb3317d846d28669d8b6f595d9 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Thu, 23 Feb 2023 09:47:47 +0100 Subject: [PATCH 03/11] feat(job-queue): deesigning methods --- include/vieter_job_queue.h | 73 +++++++++++++++++++++++++++++++++----- src/job-queue/README.md | 27 ++++++++++++++ 2 files changed, 91 insertions(+), 9 deletions(-) create mode 100644 src/job-queue/README.md diff --git a/include/vieter_job_queue.h b/include/vieter_job_queue.h index fc02d7e..aeb7e1e 100644 --- a/include/vieter_job_queue.h +++ b/include/vieter_job_queue.h @@ -14,27 +14,82 @@ typedef enum vieter_job_state { vieter_job_state_queued = 0, vieter_job_state_ready = 1, - vieter_job_state_build_finished = 2 + vieter_job_state_build_finished = 2, + vieter_job_state_failed = 3 } vieter_job_state; // This macro should be kept in sync with the above enum -#define VIETER_JOB_STATES 3 +#define VIETER_JOB_STATES 4 +/* + * Struct storing a report for why a certain job failed to be processed in the + * given state. + */ +typedef struct vieter_job_failure_report { + vieter_job_state failed_state; + char *msg; +} vieter_job_failure_report; + +vieter_job_failure_report *vieter_job_failure_report_init(); + +void vieter_job_failure_report_free(vieter_job_failure_report **ptp); + +/* + * Represents a job currently being processed in the system. A job migrates + * between different states before finally being removed from the queue. + */ typedef struct vieter_job { - int id; + uint64_t id; uint64_t next_scheduled_time; - vieter_cron_expression *ce; - bool single; - vieter_job_state state; - uint64_t state_transition_times[VIETER_JOB_STATES]; - bool dispatched; + vieter_cron_expression *schedule; void *build_config; + vieter_job_failure_report *failure_report; + uint64_t state_transition_times[VIETER_JOB_STATES]; + vieter_job_state current_state; + bool single; + bool dispatched; } vieter_job; +/* + * Allocate a new vieter_job object. + */ +vieter_job *vieter_job_init(); + +void vieter_job_free(vieter_job **ptp); + +/* + * Represents the actual queue managing the list of jobs. + */ typedef struct vieter_job_queue vieter_job_queue; +typedef enum vieter_job_queue_error { + vieter_job_queue_ok = 0, + vieter_job_queue_not_found = 1 +} vieter_job_queue_error; + +/* + * Allocate and initialize a new job queue. + */ vieter_job_queue *vieter_job_queue_init(); -void vieter_job_queue_insert(int id); +void vieter_job_queue_free(vieter_job_queue **ptp); + +/* + * Insert the given job into the system. + */ +vieter_job_queue_error vieter_job_queue_insert(vieter_job *job); + +/* + * Dispatch the job with the given id, returning the pointer to the job. + * Dispatching a job removes it from its respective state's queue. + */ +vieter_job_queue_error vieter_job_queue_dispatch(vieter_job **out, uint64_t id); + +/* + * Transition the job with the given id to the new state. This sets the + * job's dispatch flag to false, and adds it to the new state's queue. + */ +vieter_job_queue_error vieter_job_queue_transition(uint64_t id, + vieter_job_state new_state); #endif diff --git a/src/job-queue/README.md b/src/job-queue/README.md new file mode 100644 index 0000000..8fa9c94 --- /dev/null +++ b/src/job-queue/README.md @@ -0,0 +1,27 @@ +The goal of this job queue design is to process jobs in order, with each job +moving through a pipeline of tasks that need to be completed. + +At any given time, a job is in one of a few given states, e.g. "queued". These +states are explained below. Along with this, each job also has a "dispatched" +flag. If this flag is set to true, it means this job is currently being +processed. "Being processed" could mean anything; it depends entirely on the +state a job's in. While a job is dispatched, it is no longer present in the +priority queue of its respective state. + +## Job + +A job describes a scheduled build as it moves through the pipeline of states. +The job queue datastructure keeps track of all jobs in a central red-black +binary tree. For each state, a priority queue tracks in what order jobs should +be processed. + +## States + +* `queued`: a job that's in the job queue but does not yet need to be executed + (as defined by its timestamp) +* `ready`: a job that's scheduled for building, with all preprocessing tasks + fulfilled. +* `build_finished`: a job whose build has finished, and is waiting for any + post-build tasks. +* `failed`: a job whose processing failed at some point. Jobs in this state + include a failure report that describes in what state they failed, and why. -- 2.40.1 From 83b3198a49750de041e401db230ec14cdf90b3fc Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Tue, 7 Mar 2023 11:55:12 +0100 Subject: [PATCH 04/11] feat(job-queue): initial implementation of functionality --- include/vieter_job_queue.h | 44 ++++++- src/job-queue/vieter_job_queue.c | 153 ++++++++++++++++++++++ src/job-queue/vieter_job_queue_internal.h | 3 + 3 files changed, 194 insertions(+), 6 deletions(-) create mode 100644 src/job-queue/vieter_job_queue.c diff --git a/include/vieter_job_queue.h b/include/vieter_job_queue.h index aeb7e1e..6cd748f 100644 --- a/include/vieter_job_queue.h +++ b/include/vieter_job_queue.h @@ -20,6 +20,8 @@ typedef enum vieter_job_state { // This macro should be kept in sync with the above enum #define VIETER_JOB_STATES 4 +#define VIETER_JOB_INITIAL_STATE vieter_job_state_queued +#define VIETER_JOB_FAILURE_STATE vieter_job_state_failed /* * Struct storing a report for why a certain job failed to be processed in the @@ -64,7 +66,10 @@ typedef struct vieter_job_queue vieter_job_queue; typedef enum vieter_job_queue_error { vieter_job_queue_ok = 0, - vieter_job_queue_not_found = 1 + vieter_job_queue_not_present = 1, + vieter_job_queue_already_present = 2, + vieter_job_queue_state_empty = 3, + vieter_job_queue_not_dispatched = 4 } vieter_job_queue_error; /* @@ -72,24 +77,51 @@ typedef enum vieter_job_queue_error { */ vieter_job_queue *vieter_job_queue_init(); +/* + * Free a job queue. + */ void vieter_job_queue_free(vieter_job_queue **ptp); /* * Insert the given job into the system. */ -vieter_job_queue_error vieter_job_queue_insert(vieter_job *job); +vieter_job_queue_error vieter_job_queue_insert(vieter_job_queue *queue, + vieter_job *job); /* - * Dispatch the job with the given id, returning the pointer to the job. - * Dispatching a job removes it from its respective state's queue. + * Pop a job from the given state's queue. The job will then be marked as + * dispatched. */ -vieter_job_queue_error vieter_job_queue_dispatch(vieter_job **out, uint64_t id); +vieter_job_queue_error vieter_job_queue_pop(vieter_job **out, + vieter_job_queue *queue, + vieter_job_state state); /* * Transition the job with the given id to the new state. This sets the * job's dispatch flag to false, and adds it to the new state's queue. + * + * NOTE: this can only be done with dispatched jobs. */ -vieter_job_queue_error vieter_job_queue_transition(uint64_t id, +vieter_job_queue_error vieter_job_queue_transition(vieter_job_queue *queue, + uint64_t id, vieter_job_state new_state); +/* + * Remove the given job from the job queue, returning its pointer to the caller. + * + * NOTE: this can only be done with dispatched jobs. + */ +vieter_job_queue_error +vieter_job_queue_remove(vieter_job **out, vieter_job_queue *queue, uint64_t id); + +/* + * Transition a job into the failure state, and attach a failure report with the + * provided message. The message is copied, so the caller is responsible for + * freeing the provided string. + * + * NOTE: this can only be done with dispatched jobs. + */ +vieter_job_queue_error vieter_job_queue_fail(vieter_job_queue *queue, + uint64_t id, char *report_message); + #endif diff --git a/src/job-queue/vieter_job_queue.c b/src/job-queue/vieter_job_queue.c new file mode 100644 index 0000000..14ae1dc --- /dev/null +++ b/src/job-queue/vieter_job_queue.c @@ -0,0 +1,153 @@ +#include "vieter_job_queue_internal.h" + +vieter_job_queue *vieter_job_queue_init() { + vieter_job_queue *queue = malloc(sizeof(vieter_job_queue)); + + queue->tree = vieter_tree_init(); + + for (int i = 0; i < VIETER_JOB_STATES; i++) { + queue->heaps[i] = vieter_heap_init(); + } + + return queue; +} + +void vieter_job_queue_free(vieter_job_queue **ptp) { + vieter_job_queue *queue = *ptp; + + vieter_tree_free(queue->tree); + + for (int i = 0; i < VIETER_JOB_STATES; i++) { + vieter_heap_free(queue->heaps[i]); + } + + free(queue); + *ptp = NULL; +} + +vieter_job *vieter_job_init() { return calloc(1, sizeof(vieter_job)); } + +void vieter_job_free(vieter_job **ptp) { + vieter_job *job = *ptp; + + if (job->schedule != NULL) { + vieter_cron_expr_free(job->schedule); + } + + if (job->failure_report != NULL) { + vieter_job_failure_report_free(&job->failure_report); + } + + free(job); + + *ptp = NULL; +} + +vieter_job_queue_error vieter_job_queue_insert(vieter_job_queue *queue, + vieter_job *job) { + vieter_tree_error tree_res = vieter_tree_insert(queue->tree, job->id, job); + + if (tree_res != vieter_tree_ok) { + return vieter_job_queue_already_present; + } + + vieter_heap_insert(queue->heaps[VIETER_JOB_INITIAL_STATE], job->id, job); + + job->current_state = VIETER_JOB_INITIAL_STATE; + job->dispatched = false; + job->state_transition_times[VIETER_JOB_INITIAL_STATE] = time(NULL); + + return vieter_job_queue_ok; +} + +vieter_job_queue_error vieter_job_queue_pop(vieter_job **out, + vieter_job_queue *queue, + vieter_job_state state) { + vieter_heap_error res = vieter_heap_pop((void **)out, queue->heaps[state]); + + if (res != vieter_heap_ok) { + return vieter_job_queue_state_empty; + } + + (*out)->dispatched = true; + + return vieter_job_queue_ok; +} + +vieter_job_queue_error vieter_job_queue_transition(vieter_job_queue *queue, + uint64_t id, + vieter_job_state new_state) { + vieter_job *job; + + vieter_tree_error res = vieter_tree_search((void **)&job, queue->tree, id); + + if (res != vieter_tree_ok) { + return vieter_job_queue_not_present; + } + + if (!job->dispatched) { + return vieter_job_queue_not_dispatched; + } + + vieter_heap_insert(queue->heaps[new_state], job->id, job); + + job->current_state = new_state; + job->dispatched = false; + job->state_transition_times[new_state] = time(NULL); + + return vieter_job_queue_ok; +} + +vieter_job_queue_error vieter_job_queue_remove(vieter_job **out, + vieter_job_queue *queue, + uint64_t id) { + vieter_tree_error res = vieter_tree_search((void **)out, queue->tree, id); + + if (res != vieter_tree_ok) { + return vieter_job_queue_not_present; + } + + vieter_job *job = *out; + + if (!job->dispatched) { + return vieter_job_queue_not_dispatched; + } + + // This can't fail if the search succeeded + vieter_tree_remove((void **)out, queue->tree, job->id); + + return vieter_job_queue_ok; +} + +vieter_job_failure_report *vieter_job_failure_report_init() { + return calloc(1, sizeof(vieter_job_failure_report)); +} + +vieter_job_queue_error vieter_job_queue_fail(vieter_job_queue *queue, + uint64_t id, + char *report_message) { + vieter_job *job; + + vieter_tree_error res = vieter_tree_search((void **)&job, queue->tree, id); + + if (res != vieter_tree_ok) { + return vieter_job_queue_not_present; + } + + if (!job->dispatched) { + return vieter_job_queue_not_dispatched; + } + + vieter_heap_insert(queue->heaps[VIETER_JOB_FAILURE_STATE], job->id, job); + + job->dispatched = false; + job->state_transition_times[VIETER_JOB_FAILURE_STATE] = time(NULL); + + job->failure_report = vieter_job_failure_report_init(); + job->failure_report->failed_state = job->current_state; + job->failure_report->msg = strdup(report_message); + + job->current_state = VIETER_JOB_FAILURE_STATE; + + return vieter_job_queue_ok; +} diff --git a/src/job-queue/vieter_job_queue_internal.h b/src/job-queue/vieter_job_queue_internal.h index 8d8ffc4..dac8b97 100644 --- a/src/job-queue/vieter_job_queue_internal.h +++ b/src/job-queue/vieter_job_queue_internal.h @@ -1,10 +1,13 @@ #ifndef VIETER_JOB_QUEUE_INTERNAL #define VIETER_JOB_QUEUE_INTERNAL +#include "vieter_heap.h" +#include "vieter_job_queue.h" #include "vieter_tree.h" struct vieter_job_queue { vieter_tree *tree; + vieter_heap *heaps[VIETER_JOB_STATES]; }; #endif -- 2.40.1 From 1c563d84215aa021312463aed8793fb37bb4a4ad Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Tue, 7 Mar 2023 12:12:46 +0100 Subject: [PATCH 05/11] feat(tree): add rwlock --- include/vieter_tree.h | 18 ++++++++++++++++++ src/tree/vieter_tree.c | 12 ++++++++++++ src/tree/vieter_tree_internal.h | 2 ++ 3 files changed, 32 insertions(+) diff --git a/include/vieter_tree.h b/include/vieter_tree.h index 2079eb9..4da500f 100644 --- a/include/vieter_tree.h +++ b/include/vieter_tree.h @@ -67,4 +67,22 @@ void vieter_tree_iterator_free(vieter_tree_iterator **ptp); vieter_tree_error vieter_tree_iterator_next(void **out, vieter_tree_iterator *iter); +/* + * Acquire a read lock on the tree. Return value is the result of + * pthread_rwlock_rdlock. + */ +int vieter_tree_rlock(vieter_tree *tree); + +/* + * Acquire a write lock on the tree. Return value is the result of + * pthread_rwlock_wrlock. + */ +int vieter_tree_wlock(vieter_tree *tree); + +/* + * Unlock the lock after having acquired it. Return value is the result of + * pthread_rwlock_unlock. + */ +int vieter_tree_unlock(vieter_tree *tree); + #endif diff --git a/src/tree/vieter_tree.c b/src/tree/vieter_tree.c index 84a1a26..ca6016e 100644 --- a/src/tree/vieter_tree.c +++ b/src/tree/vieter_tree.c @@ -114,3 +114,15 @@ bool vieter_tree_validate(vieter_tree *tree) { return vieter_tree_node_get(tree->root, vieter_tree_node_black) && vieter_tree_node_validate(tree->root, 0, expected_black_nodes); } + +int vieter_tree_rlock(vieter_tree *tree) { + return pthread_rwlock_rdlock(&tree->lock); +} + +int vieter_tree_wlock(vieter_tree *tree) { + return pthread_rwlock_wrlock(&tree->lock); +} + +int vieter_tree_unlock(vieter_tree *tree) { + return pthread_rwlock_unlock(&tree->lock); +} diff --git a/src/tree/vieter_tree_internal.h b/src/tree/vieter_tree_internal.h index 1214572..037345c 100644 --- a/src/tree/vieter_tree_internal.h +++ b/src/tree/vieter_tree_internal.h @@ -1,11 +1,13 @@ #include "vieter_tree.h" #include "vieter_tree_node.h" +#include #include struct vieter_tree { uint64_t size; vieter_tree_node *root; + pthread_rwlock_t lock; }; /* -- 2.40.1 From 8e076f8543408337aab96b7010722f5597ba4836 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Tue, 7 Mar 2023 12:43:31 +0100 Subject: [PATCH 06/11] feat(cat-heap): initial implementation --- include/vieter_cat_heap.h | 30 ++++++ include/vieter_job_queue.h | 17 ++++ src/cat-heap/README.md | 4 + src/cat-heap/vieter_cat_heap.c | 107 ++++++++++++++++++++++ src/cat-heap/vieter_cat_heap_internal.h | 10 ++ src/job-queue/vieter_job_queue.c | 13 +++ src/job-queue/vieter_job_queue_internal.h | 2 + 7 files changed, 183 insertions(+) create mode 100644 include/vieter_cat_heap.h create mode 100644 src/cat-heap/README.md create mode 100644 src/cat-heap/vieter_cat_heap.c create mode 100644 src/cat-heap/vieter_cat_heap_internal.h diff --git a/include/vieter_cat_heap.h b/include/vieter_cat_heap.h new file mode 100644 index 0000000..d6b2a83 --- /dev/null +++ b/include/vieter_cat_heap.h @@ -0,0 +1,30 @@ +#ifndef VIETER_CAT_HEAP +#define VIETER_CAT_HEAP + +#include + +typedef struct vieter_cat_heap vieter_cat_heap; + +typedef enum vieter_cat_heap_error { + vieter_cat_heap_ok = 0, + vieter_cat_heap_arch_empty = 1, + vieter_cat_heap_arch_not_found = 2 +} vieter_cat_heap_error; + +vieter_cat_heap *vieter_cat_heap_init(); + +void vieter_cat_heap_free(vieter_cat_heap **ptp); + +uint64_t vieter_cat_heap_size(vieter_cat_heap *cheap); + +vieter_cat_heap_error vieter_cat_heap_insert(vieter_cat_heap *cheap, + char *category, uint64_t key, + void *data); + +vieter_cat_heap_error vieter_cat_heap_pop(void **out, vieter_cat_heap *cheap, + char *category); + +vieter_cat_heap_error vieter_cat_heap_peek(void **out, vieter_cat_heap *cheap, + char *category); + +#endif diff --git a/include/vieter_job_queue.h b/include/vieter_job_queue.h index 6cd748f..92ef35f 100644 --- a/include/vieter_job_queue.h +++ b/include/vieter_job_queue.h @@ -123,5 +123,22 @@ vieter_job_queue_remove(vieter_job **out, vieter_job_queue *queue, uint64_t id); */ vieter_job_queue_error vieter_job_queue_fail(vieter_job_queue *queue, uint64_t id, char *report_message); +/* + * Acquire a read lock on the job queue. Return value is the result of + * pthread_rwlock_rdlock. + */ +int vieter_job_queue_rlock(vieter_job_queue *job_queue); + +/* + * Acquire a write lock on the job queue. Return value is the result of + * pthread_rwlock_wrlock. + */ +int vieter_job_queue_wlock(vieter_job_queue *job_queue); + +/* + * Unlock the lock after having acquired it. Return value is the result of + * pthread_rwlock_unlock. + */ +int vieter_job_queue_unlock(vieter_job_queue *job_queue); #endif diff --git a/src/cat-heap/README.md b/src/cat-heap/README.md new file mode 100644 index 0000000..bbdfa0b --- /dev/null +++ b/src/cat-heap/README.md @@ -0,0 +1,4 @@ +A category heap consists of a collection of heaps, with each heap representing +a certain category. In practice, this category would be an architecture (e.g. +`x86_64`). This is used by the job queue to have a queue for each architecture +for a given state. diff --git a/src/cat-heap/vieter_cat_heap.c b/src/cat-heap/vieter_cat_heap.c new file mode 100644 index 0000000..b514b5b --- /dev/null +++ b/src/cat-heap/vieter_cat_heap.c @@ -0,0 +1,107 @@ +#include "vieter_cat_heap_internal.h" + +vieter_cat_heap *vieter_cat_heap_init() { + return calloc(1, sizeof(vieter_cat_heap)); +} + +void vieter_cat_heap_free(vieter_cat_heap **ptp) { + vieter_cat_heap *cheap = *ptp; + + if (cheap->cat_count > 0) { + for (uint64_t i = 0; i < cheap->cat_count; i++) { + free(cheap->categories[i]); + vieter_heap_free(cheap->heaps[i]); + } + + free(cheap->categories); + free(cheap->heaps); + } + + free(cheap); + *ptp = NULL; +} + +uint64_t vieter_cat_heap_size(vieter_cat_heap *cheap) { + uint64_t total = 0; + + for (uint64_t i = 0; i < cheap->cat_count; i++) { + total += vieter_heap_size(cheap->heaps[i]); + } + + return total; +} + +vieter_cat_heap_error vieter_cat_heap_insert(vieter_cat_heap *cheap, + char *category, uint64_t key, + void *data) { + uint64_t i = 0; + + // For now, we do a linear search through all categories. This is more than + // fast enough for most usecases. + while (i < cheap->cat_count && strcmp(category, cheap->categories[i]) != 0) { + i++; + } + + if (i == cheap->cat_count) { + if (cheap->cat_count == 0) { + cheap->categories = malloc(sizeof(char *)); + cheap->heaps = malloc(sizeof(vieter_heap *)); + } else { + cheap->categories = + realloc(cheap->categories, sizeof(char *) * (cheap->cat_count + 1)); + cheap->heaps = + realloc(cheap->heaps, sizeof(vieter_heap *) * (cheap->cat_count + 1)); + } + + cheap->cat_count++; + + cheap->categories[i] = strdup(category); + cheap->heaps[i] = vieter_heap_init(); + } + + vieter_heap_insert(cheap->heaps[i], key, data); + + return vieter_cat_heap_ok; +} + +vieter_cat_heap_error vieter_cat_heap_pop(void **out, vieter_cat_heap *cheap, + char *category) { + uint64_t i = 0; + + while (i < cheap->cat_count && strcmp(category, cheap->categories[i]) != 0) { + i++; + } + + if (i == cheap->cat_count) { + return vieter_cat_heap_arch_not_found; + } + + vieter_heap_error res = vieter_heap_pop(out, cheap->heaps[i]); + + if (res != vieter_heap_ok) { + return vieter_cat_heap_arch_empty; + } + + return vieter_cat_heap_ok; +} + +vieter_cat_heap_error vieter_cat_heap_peek(void **out, vieter_cat_heap *cheap, + char *category) { + uint64_t i = 0; + + while (i < cheap->cat_count && strcmp(category, cheap->categories[i]) != 0) { + i++; + } + + if (i == cheap->cat_count) { + return vieter_cat_heap_arch_not_found; + } + + vieter_heap_error res = vieter_heap_peek(out, cheap->heaps[i]); + + if (res != vieter_heap_ok) { + return vieter_cat_heap_arch_empty; + } + + return vieter_cat_heap_ok; +} diff --git a/src/cat-heap/vieter_cat_heap_internal.h b/src/cat-heap/vieter_cat_heap_internal.h new file mode 100644 index 0000000..a4a3f2c --- /dev/null +++ b/src/cat-heap/vieter_cat_heap_internal.h @@ -0,0 +1,10 @@ +#include "vieter_cat_heap.h" +#include "vieter_heap.h" +#include +#include + +struct vieter_cat_heap { + uint64_t cat_count; + char **categories; + vieter_heap **heaps; +}; diff --git a/src/job-queue/vieter_job_queue.c b/src/job-queue/vieter_job_queue.c index 14ae1dc..a5fb9e3 100644 --- a/src/job-queue/vieter_job_queue.c +++ b/src/job-queue/vieter_job_queue.c @@ -63,6 +63,7 @@ vieter_job_queue_error vieter_job_queue_insert(vieter_job_queue *queue, vieter_job_queue_error vieter_job_queue_pop(vieter_job **out, vieter_job_queue *queue, vieter_job_state state) { + vieter_heap_error res = vieter_heap_pop((void **)out, queue->heaps[state]); if (res != vieter_heap_ok) { @@ -151,3 +152,15 @@ vieter_job_queue_error vieter_job_queue_fail(vieter_job_queue *queue, return vieter_job_queue_ok; } + +int vieter_job_queue_rlock(vieter_job_queue *job_queue) { + return pthread_rwlock_rdlock(&job_queue->lock); +} + +int vieter_job_queue_wlock(vieter_job_queue *job_queue) { + return pthread_rwlock_wrlock(&job_queue->lock); +} + +int vieter_job_queue_unlock(vieter_job_queue *job_queue) { + return pthread_rwlock_unlock(&job_queue->lock); +} diff --git a/src/job-queue/vieter_job_queue_internal.h b/src/job-queue/vieter_job_queue_internal.h index dac8b97..4641ba6 100644 --- a/src/job-queue/vieter_job_queue_internal.h +++ b/src/job-queue/vieter_job_queue_internal.h @@ -4,10 +4,12 @@ #include "vieter_heap.h" #include "vieter_job_queue.h" #include "vieter_tree.h" +#include struct vieter_job_queue { vieter_tree *tree; vieter_heap *heaps[VIETER_JOB_STATES]; + pthread_rwlock_t lock; }; #endif -- 2.40.1 From 1f4887118f7eec4dcfbf9f0275d4244a2a143b3f Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sat, 1 Apr 2023 17:04:40 +0200 Subject: [PATCH 07/11] feat(job-queue): add cat-heap support --- include/vieter_cat_heap.h | 2 +- include/vieter_job_queue.h | 22 ++++++++-- src/cat-heap/vieter_cat_heap.c | 5 +-- src/job-queue/vieter_job_queue.c | 51 ++++++++++++++++++++--- src/job-queue/vieter_job_queue_internal.h | 6 ++- 5 files changed, 71 insertions(+), 15 deletions(-) diff --git a/include/vieter_cat_heap.h b/include/vieter_cat_heap.h index d6b2a83..f25df00 100644 --- a/include/vieter_cat_heap.h +++ b/include/vieter_cat_heap.h @@ -13,7 +13,7 @@ typedef enum vieter_cat_heap_error { vieter_cat_heap *vieter_cat_heap_init(); -void vieter_cat_heap_free(vieter_cat_heap **ptp); +void vieter_cat_heap_free(vieter_cat_heap *cheap); uint64_t vieter_cat_heap_size(vieter_cat_heap *cheap); diff --git a/include/vieter_job_queue.h b/include/vieter_job_queue.h index 92ef35f..9fb2c96 100644 --- a/include/vieter_job_queue.h +++ b/include/vieter_job_queue.h @@ -20,8 +20,12 @@ typedef enum vieter_job_state { // This macro should be kept in sync with the above enum #define VIETER_JOB_STATES 4 +// Neither of these states are allowed to be categorized #define VIETER_JOB_INITIAL_STATE vieter_job_state_queued #define VIETER_JOB_FAILURE_STATE vieter_job_state_failed +// Bitmap describing what states should be divided into multiple architectures +#define VIETER_JOB_STATES_ARCH 0b0010 +#define VIETER_JOB_STATE_IS_ARCH(i) (VIETER_JOB_STATES_ARCH & (1 << i)) /* * Struct storing a report for why a certain job failed to be processed in the @@ -45,6 +49,7 @@ typedef struct vieter_job { uint64_t next_scheduled_time; vieter_cron_expression *schedule; void *build_config; + char *arch; vieter_job_failure_report *failure_report; uint64_t state_transition_times[VIETER_JOB_STATES]; vieter_job_state current_state; @@ -69,7 +74,9 @@ typedef enum vieter_job_queue_error { vieter_job_queue_not_present = 1, vieter_job_queue_already_present = 2, vieter_job_queue_state_empty = 3, - vieter_job_queue_not_dispatched = 4 + vieter_job_queue_not_dispatched = 4, + vieter_job_queue_state_is_arch = 5, + vieter_job_queue_state_is_not_arch = 6, } vieter_job_queue_error; /* @@ -89,13 +96,22 @@ vieter_job_queue_error vieter_job_queue_insert(vieter_job_queue *queue, vieter_job *job); /* - * Pop a job from the given state's queue. The job will then be marked as - * dispatched. + * Pop a job from the given non-categorized state's queue. The job will then be + * marked as dispatched. */ vieter_job_queue_error vieter_job_queue_pop(vieter_job **out, vieter_job_queue *queue, vieter_job_state state); +/* + * Pop a job from the given categorized state's queue. The job will then be + * marked as dispatched. + */ +vieter_job_queue_error vieter_job_queue_pop_arch(vieter_job **out, + vieter_job_queue *queue, + vieter_job_state state, + char *arch); + /* * Transition the job with the given id to the new state. This sets the * job's dispatch flag to false, and adds it to the new state's queue. diff --git a/src/cat-heap/vieter_cat_heap.c b/src/cat-heap/vieter_cat_heap.c index b514b5b..d0a00a0 100644 --- a/src/cat-heap/vieter_cat_heap.c +++ b/src/cat-heap/vieter_cat_heap.c @@ -4,9 +4,7 @@ vieter_cat_heap *vieter_cat_heap_init() { return calloc(1, sizeof(vieter_cat_heap)); } -void vieter_cat_heap_free(vieter_cat_heap **ptp) { - vieter_cat_heap *cheap = *ptp; - +void vieter_cat_heap_free(vieter_cat_heap *cheap) { if (cheap->cat_count > 0) { for (uint64_t i = 0; i < cheap->cat_count; i++) { free(cheap->categories[i]); @@ -18,7 +16,6 @@ void vieter_cat_heap_free(vieter_cat_heap **ptp) { } free(cheap); - *ptp = NULL; } uint64_t vieter_cat_heap_size(vieter_cat_heap *cheap) { diff --git a/src/job-queue/vieter_job_queue.c b/src/job-queue/vieter_job_queue.c index a5fb9e3..0fd3c09 100644 --- a/src/job-queue/vieter_job_queue.c +++ b/src/job-queue/vieter_job_queue.c @@ -6,7 +6,11 @@ vieter_job_queue *vieter_job_queue_init() { queue->tree = vieter_tree_init(); for (int i = 0; i < VIETER_JOB_STATES; i++) { - queue->heaps[i] = vieter_heap_init(); + if (VIETER_JOB_STATE_IS_ARCH(i)) { + queue->heaps[i].cat_heap = vieter_cat_heap_init(); + } else { + queue->heaps[i].heap = vieter_heap_init(); + } } return queue; @@ -18,7 +22,11 @@ void vieter_job_queue_free(vieter_job_queue **ptp) { vieter_tree_free(queue->tree); for (int i = 0; i < VIETER_JOB_STATES; i++) { - vieter_heap_free(queue->heaps[i]); + if (VIETER_JOB_STATE_IS_ARCH(i)) { + vieter_cat_heap_free(queue->heaps[i].cat_heap); + } else { + vieter_heap_free(queue->heaps[i].heap); + } } free(queue); @@ -51,7 +59,8 @@ vieter_job_queue_error vieter_job_queue_insert(vieter_job_queue *queue, return vieter_job_queue_already_present; } - vieter_heap_insert(queue->heaps[VIETER_JOB_INITIAL_STATE], job->id, job); + // We assume that the initial state is not a category heap + vieter_heap_insert(queue->heaps[VIETER_JOB_INITIAL_STATE].heap, job->id, job); job->current_state = VIETER_JOB_INITIAL_STATE; job->dispatched = false; @@ -63,8 +72,12 @@ vieter_job_queue_error vieter_job_queue_insert(vieter_job_queue *queue, vieter_job_queue_error vieter_job_queue_pop(vieter_job **out, vieter_job_queue *queue, vieter_job_state state) { + if (VIETER_JOB_STATE_IS_ARCH(state)) { + return vieter_job_queue_state_is_arch; + } - vieter_heap_error res = vieter_heap_pop((void **)out, queue->heaps[state]); + vieter_heap_error res = + vieter_heap_pop((void **)out, queue->heaps[state].heap); if (res != vieter_heap_ok) { return vieter_job_queue_state_empty; @@ -75,6 +88,26 @@ vieter_job_queue_error vieter_job_queue_pop(vieter_job **out, return vieter_job_queue_ok; } +vieter_job_queue_error vieter_job_queue_pop_arch(vieter_job **out, + vieter_job_queue *queue, + vieter_job_state state, + char *arch) { + if (!VIETER_JOB_STATE_IS_ARCH(state)) { + return vieter_job_queue_state_is_not_arch; + } + + vieter_cat_heap_error res = + vieter_cat_heap_pop((void **)out, queue->heaps[state].cat_heap, arch); + + if (res != vieter_cat_heap_ok) { + return vieter_job_queue_state_empty; + } + + (*out)->dispatched = true; + + return vieter_job_queue_ok; +} + vieter_job_queue_error vieter_job_queue_transition(vieter_job_queue *queue, uint64_t id, vieter_job_state new_state) { @@ -90,7 +123,12 @@ vieter_job_queue_error vieter_job_queue_transition(vieter_job_queue *queue, return vieter_job_queue_not_dispatched; } - vieter_heap_insert(queue->heaps[new_state], job->id, job); + if (VIETER_JOB_STATE_IS_ARCH(new_state)) { + vieter_cat_heap_insert(queue->heaps[new_state].cat_heap, job->arch, job->id, + job); + } else { + vieter_heap_insert(queue->heaps[new_state].heap, job->id, job); + } job->current_state = new_state; job->dispatched = false; @@ -139,7 +177,8 @@ vieter_job_queue_error vieter_job_queue_fail(vieter_job_queue *queue, return vieter_job_queue_not_dispatched; } - vieter_heap_insert(queue->heaps[VIETER_JOB_FAILURE_STATE], job->id, job); + // We assume the failure state is not categorized + vieter_heap_insert(queue->heaps[VIETER_JOB_FAILURE_STATE].heap, job->id, job); job->dispatched = false; job->state_transition_times[VIETER_JOB_FAILURE_STATE] = time(NULL); diff --git a/src/job-queue/vieter_job_queue_internal.h b/src/job-queue/vieter_job_queue_internal.h index 4641ba6..99ecab8 100644 --- a/src/job-queue/vieter_job_queue_internal.h +++ b/src/job-queue/vieter_job_queue_internal.h @@ -1,6 +1,7 @@ #ifndef VIETER_JOB_QUEUE_INTERNAL #define VIETER_JOB_QUEUE_INTERNAL +#include "vieter_cat_heap.h" #include "vieter_heap.h" #include "vieter_job_queue.h" #include "vieter_tree.h" @@ -8,7 +9,10 @@ struct vieter_job_queue { vieter_tree *tree; - vieter_heap *heaps[VIETER_JOB_STATES]; + union { + vieter_heap *heap; + vieter_cat_heap *cat_heap; + } heaps[VIETER_JOB_STATES]; pthread_rwlock_t lock; }; -- 2.40.1 From c7d2db4e42794c09338639817a52bd8081ddafad Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sat, 1 Apr 2023 17:24:25 +0200 Subject: [PATCH 08/11] fix(job-queue): use time as key for heaps --- src/job-queue/vieter_job_queue.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/job-queue/vieter_job_queue.c b/src/job-queue/vieter_job_queue.c index 0fd3c09..32621fc 100644 --- a/src/job-queue/vieter_job_queue.c +++ b/src/job-queue/vieter_job_queue.c @@ -60,7 +60,8 @@ vieter_job_queue_error vieter_job_queue_insert(vieter_job_queue *queue, } // We assume that the initial state is not a category heap - vieter_heap_insert(queue->heaps[VIETER_JOB_INITIAL_STATE].heap, job->id, job); + vieter_heap_insert(queue->heaps[VIETER_JOB_INITIAL_STATE].heap, + job->next_scheduled_time, job); job->current_state = VIETER_JOB_INITIAL_STATE; job->dispatched = false; @@ -124,10 +125,11 @@ vieter_job_queue_error vieter_job_queue_transition(vieter_job_queue *queue, } if (VIETER_JOB_STATE_IS_ARCH(new_state)) { - vieter_cat_heap_insert(queue->heaps[new_state].cat_heap, job->arch, job->id, - job); + vieter_cat_heap_insert(queue->heaps[new_state].cat_heap, job->arch, + job->next_scheduled_time, job); } else { - vieter_heap_insert(queue->heaps[new_state].heap, job->id, job); + vieter_heap_insert(queue->heaps[new_state].heap, job->next_scheduled_time, + job); } job->current_state = new_state; @@ -178,7 +180,8 @@ vieter_job_queue_error vieter_job_queue_fail(vieter_job_queue *queue, } // We assume the failure state is not categorized - vieter_heap_insert(queue->heaps[VIETER_JOB_FAILURE_STATE].heap, job->id, job); + vieter_heap_insert(queue->heaps[VIETER_JOB_FAILURE_STATE].heap, + job->next_scheduled_time, job); job->dispatched = false; job->state_transition_times[VIETER_JOB_FAILURE_STATE] = time(NULL); -- 2.40.1 From ec6e217801be0385e3ca18cc34a2073e54e19fb8 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Tue, 4 Apr 2023 14:47:18 +0200 Subject: [PATCH 09/11] test: add some cat-heap tests --- Makefile | 6 ++++ test/cat-heap/test_cat_heap.c | 52 +++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 test/cat-heap/test_cat_heap.c diff --git a/Makefile b/Makefile index 9db32d4..78f6a1c 100644 --- a/Makefile +++ b/Makefile @@ -98,5 +98,11 @@ clean: rm -rf $(BUILD_DIR) +.PHONY: bear +bear: clean + bear -- make + bear --append -- make build-test + + # Make make aware of the .d files -include $(DEPS) diff --git a/test/cat-heap/test_cat_heap.c b/test/cat-heap/test_cat_heap.c new file mode 100644 index 0000000..d415198 --- /dev/null +++ b/test/cat-heap/test_cat_heap.c @@ -0,0 +1,52 @@ +#include "acutest.h" +#include "vieter_cat_heap_internal.h" + +#define TEST_SIZE(cheap, size) \ + TEST_CHECK(vieter_cat_heap_size(cheap) == size); \ + TEST_MSG("Size: %zu, expected: %lu", vieter_cat_heap_size(cheap), (uint64_t)size) + +void test_init() { + vieter_cat_heap *cheap = vieter_cat_heap_init(); + TEST_CHECK(cheap != NULL); + TEST_SIZE(cheap, 0); + vieter_cat_heap_free(cheap); +} + +void test_insert() { + vieter_cat_heap *cheap = vieter_cat_heap_init(); + TEST_SIZE(cheap, 0); + + void *data; + + for (uint64_t i = 50; i > 0; i--) { + vieter_cat_heap_insert(cheap, "cat1", i, (void *)i); + TEST_SIZE(cheap, (uint64_t)51 - i); + + data = 0; + + TEST_CHECK(vieter_cat_heap_peek(&data, cheap, "cat1") == vieter_cat_heap_ok); + TEST_CHECK_(data == (void *)i, "%lX == %lX", (uint64_t)data, i); + } + + for (uint64_t i = 50; i > 0; i--) { + vieter_cat_heap_insert(cheap, "cat2", i, (void *)i); + TEST_SIZE(cheap, (uint64_t)101 - i); + + data = 0; + + TEST_CHECK(vieter_cat_heap_peek(&data, cheap, "cat2") == vieter_cat_heap_ok); + TEST_CHECK_(data == (void *)i, "%lX == %lX", (uint64_t)data, i); + } + + vieter_cat_heap_free(cheap); +} + + +TEST_LIST = { + {"cat heap init", test_init}, + {"cat heap insert", test_insert}, + /* {"heap insert random", test_insert_random}, */ + /* {"heap pop", test_pop}, */ + /* {"heap pop random", test_pop_random}, */ + {NULL, NULL} +}; -- 2.40.1 From 07f793d768cc72540dfc2d5fa6a5d6c112efaf67 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Tue, 4 Apr 2023 14:57:31 +0200 Subject: [PATCH 10/11] refactor(job-queue): change free functions --- include/vieter_job_queue.h | 6 +++--- src/job-queue/vieter_job.c | 24 ++++++++++++++++++++++++ src/job-queue/vieter_job_queue.c | 27 +-------------------------- 3 files changed, 28 insertions(+), 29 deletions(-) create mode 100644 src/job-queue/vieter_job.c diff --git a/include/vieter_job_queue.h b/include/vieter_job_queue.h index 9fb2c96..cded82f 100644 --- a/include/vieter_job_queue.h +++ b/include/vieter_job_queue.h @@ -38,7 +38,7 @@ typedef struct vieter_job_failure_report { vieter_job_failure_report *vieter_job_failure_report_init(); -void vieter_job_failure_report_free(vieter_job_failure_report **ptp); +void vieter_job_failure_report_free(vieter_job_failure_report *report); /* * Represents a job currently being processed in the system. A job migrates @@ -62,7 +62,7 @@ typedef struct vieter_job { */ vieter_job *vieter_job_init(); -void vieter_job_free(vieter_job **ptp); +void vieter_job_free(vieter_job *job); /* * Represents the actual queue managing the list of jobs. @@ -87,7 +87,7 @@ vieter_job_queue *vieter_job_queue_init(); /* * Free a job queue. */ -void vieter_job_queue_free(vieter_job_queue **ptp); +void vieter_job_queue_free(vieter_job_queue *queue); /* * Insert the given job into the system. diff --git a/src/job-queue/vieter_job.c b/src/job-queue/vieter_job.c new file mode 100644 index 0000000..15633c1 --- /dev/null +++ b/src/job-queue/vieter_job.c @@ -0,0 +1,24 @@ +#include "vieter_job_queue_internal.h" + +vieter_job *vieter_job_init() { return calloc(1, sizeof(vieter_job)); } + +void vieter_job_free(vieter_job *job) { + if (job->schedule != NULL) { + vieter_cron_expr_free(job->schedule); + } + + if (job->failure_report != NULL) { + vieter_job_failure_report_free(job->failure_report); + } + + free(job); +} + +vieter_job_failure_report *vieter_job_failure_report_init() { + return calloc(1, sizeof(vieter_job_failure_report)); +} + +void vieter_job_failure_report_free(vieter_job_failure_report *report) { + free(report->msg); + free(report); +} diff --git a/src/job-queue/vieter_job_queue.c b/src/job-queue/vieter_job_queue.c index 32621fc..028b1af 100644 --- a/src/job-queue/vieter_job_queue.c +++ b/src/job-queue/vieter_job_queue.c @@ -16,9 +16,7 @@ vieter_job_queue *vieter_job_queue_init() { return queue; } -void vieter_job_queue_free(vieter_job_queue **ptp) { - vieter_job_queue *queue = *ptp; - +void vieter_job_queue_free(vieter_job_queue *queue) { vieter_tree_free(queue->tree); for (int i = 0; i < VIETER_JOB_STATES; i++) { @@ -30,25 +28,6 @@ void vieter_job_queue_free(vieter_job_queue **ptp) { } free(queue); - *ptp = NULL; -} - -vieter_job *vieter_job_init() { return calloc(1, sizeof(vieter_job)); } - -void vieter_job_free(vieter_job **ptp) { - vieter_job *job = *ptp; - - if (job->schedule != NULL) { - vieter_cron_expr_free(job->schedule); - } - - if (job->failure_report != NULL) { - vieter_job_failure_report_free(&job->failure_report); - } - - free(job); - - *ptp = NULL; } vieter_job_queue_error vieter_job_queue_insert(vieter_job_queue *queue, @@ -160,10 +139,6 @@ vieter_job_queue_error vieter_job_queue_remove(vieter_job **out, return vieter_job_queue_ok; } -vieter_job_failure_report *vieter_job_failure_report_init() { - return calloc(1, sizeof(vieter_job_failure_report)); -} - vieter_job_queue_error vieter_job_queue_fail(vieter_job_queue *queue, uint64_t id, char *report_message) { -- 2.40.1 From 4f46920025a6a0776594ceb019970270f758d356 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sat, 6 May 2023 11:39:27 +0200 Subject: [PATCH 11/11] test: small job queue test --- test/job-queue/test_job_queue.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 test/job-queue/test_job_queue.c diff --git a/test/job-queue/test_job_queue.c b/test/job-queue/test_job_queue.c new file mode 100644 index 0000000..3187cda --- /dev/null +++ b/test/job-queue/test_job_queue.c @@ -0,0 +1,23 @@ +#include "acutest.h" +#include "vieter_job_queue_internal.h" + +void test_init() { + vieter_job_queue *queue = vieter_job_queue_init(); + TEST_CHECK(queue != NULL); + vieter_job_queue_free(queue); +} + +void test_job_path() { + vieter_job_queue *queue = vieter_job_queue_init(); + TEST_CHECK(queue != NULL); + + vieter_job *job = vieter_job_init(); + job->next_scheduled_time = 5; + + vieter_job_queue_free(queue); +} + +TEST_LIST = { + {"job queue init", test_init}, + {NULL, NULL} +}; -- 2.40.1