#ifndef VIETER_JOB_QUEUE #define VIETER_JOB_QUEUE #include "vieter_cron.h" #include #include /* * 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_state_queued = 0, vieter_job_state_ready = 1, 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 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 * 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 { uint64_t id; 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; 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_present = 1, vieter_job_queue_already_present = 2, vieter_job_queue_state_empty = 3, 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; /* * Allocate and initialize a new job queue. */ 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_queue *queue, vieter_job *job); /* * 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. * * NOTE: this can only be done with dispatched jobs. */ 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); /* * 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