diff options
author | sinanmohd <sinan@sinanmohd.com> | 2024-06-20 21:03:29 +0530 |
---|---|---|
committer | sinanmohd <sinan@sinanmohd.com> | 2024-06-20 21:07:23 +0530 |
commit | 36be4b06236ef60234ac8d6fe3962208c880c163 (patch) | |
tree | 0a8d54871899f80434ae7076fb57f770ee7fabe4 | |
parent | af3ee1af961d21f106cf6ccc9606c6043f13d977 (diff) |
jobs: improve the DAG implementation
maintain a record of parent nodes for efficient node removal
-rw-r--r-- | include/jobs.h | 4 | ||||
-rw-r--r-- | src/jobs.c | 98 |
2 files changed, 82 insertions, 20 deletions
diff --git a/include/jobs.h b/include/jobs.h index d223ec2..85d606b 100644 --- a/include/jobs.h +++ b/include/jobs.h @@ -16,6 +16,9 @@ struct job { size_t deps_size, deps_filled; struct job **deps; + size_t parents_size, parents_filled; + struct job **parents; + CIRCLEQ_ENTRY(job) clist; }; CIRCLEQ_HEAD(job_clist, job); @@ -29,7 +32,6 @@ typedef enum { int job_read(FILE *stream, struct job **jobs); int jobs_init(FILE **stream); -int job_new(struct job **j, char *name, char *drv_path); void job_free(struct job *j); #define JOBS_H @@ -9,11 +9,15 @@ #include "util.h" static void output_free(struct output *output); +static int job_new(struct job **j, char *name, char *drv_path, + struct job *parent); static int job_output_insert(struct job *j, char *name, char *store_path); static int job_read_inputdrvs(struct job *job, cJSON *input_drvs); static int job_read_outputs(struct job *job, cJSON *outputs); static int job_deps_list_insert(struct job *job, struct job *dep); static int job_output_list_insert(struct job *job, struct output *output); +static int job_parents_list_insert(struct job *job, struct job *parent); +static void job_deps_list_rm(struct job *job, struct job *dep); static void output_free(struct output *output) { @@ -28,7 +32,7 @@ static void output_free(struct output *output) static int job_output_list_insert(struct job *job, struct output *output) { - size_t newsize = 0; + size_t newsize; void *ret; if (job->outputs_filled < job->outputs_size) { @@ -50,9 +54,21 @@ static int job_output_list_insert(struct job *job, struct output *output) return 0; } +static void job_deps_list_rm(struct job *job, struct job *dep) +{ + for (size_t i = 0; i < job->deps_filled; i++) { + if (job->deps[i] != dep) + continue; + + job->deps[i] = job->deps[job->deps_filled - 1]; + job->deps_filled -= 1; + return; + } +} + static int job_deps_list_insert(struct job *job, struct job *dep) { - size_t newsize = 0; + size_t newsize; void *ret; if (job->deps_filled < job->deps_size) { @@ -74,6 +90,30 @@ static int job_deps_list_insert(struct job *job, struct job *dep) return 0; } +static int job_parents_list_insert(struct job *job, struct job *parent) +{ + size_t newsize; + void *ret; + + if (job->parents_filled < job->parents_size) { + job->parents[job->parents_filled++] = parent; + return 0; + } + + newsize = job->parents_size == 0 ? 1 : job->parents_size * 2; + ret = realloc(job->parents, newsize * sizeof(*job->parents)); + if (ret == NULL) { + print_err("%s", strerror(errno)); + return -errno; + } + + job->parents = ret; + job->parents_size = newsize; + job->parents[job->parents_filled++] = parent; + + return 0; +} + static int job_output_insert(struct job *j, char *name, char *store_path) { struct output *o; @@ -127,12 +167,13 @@ static int job_read_inputdrvs(struct job *job, cJSON *input_drvs) int ret = 0; for (cJSON *array = input_drvs; array != NULL; array = array->next) { - ret = job_new(&dep_job, NULL, array->string); + ret = job_new(&dep_job, NULL, array->string, job); if (ret < 0) goto out_free_dep_job; cJSON_ArrayForEach (output, array) { - ret = job_output_insert(dep_job, output->valuestring, NULL); + ret = job_output_insert(dep_job, output->valuestring, + NULL); if (ret < 0) job_free(dep_job); } @@ -200,7 +241,7 @@ int job_read(FILE *stream, struct job **job) } drv_path = temp->valuestring; - ret = job_new(&j, name, drv_path); + ret = job_new(&j, name, drv_path, NULL); if (ret < 0) goto out_free; @@ -239,21 +280,27 @@ void job_free(struct job *job) if (job == NULL) return; - free(job->name); - free(job->drv_path); + /* deps_filled will be decremented by recusrive call to the job_free + * see job_deps_list_rm() in the next for loop */ + while (job->deps_filled) + job_free(*job->deps); + free(job->deps); + + for (size_t i = 0; i < job->parents_filled; i++) + job_deps_list_rm(job->parents[i], job); + free(job->parents); for (size_t i = 0; i < job->outputs_filled; i++) output_free(job->outputs[i]); free(job->outputs); - for (size_t i = 0; i < job->deps_filled; i++) - job_free(job->deps[i]); - free(job->deps); - + free(job->drv_path); + free(job->name); free(job); } -int job_new(struct job **j, char *name, char *drv_path) +static int job_new(struct job **j, char *name, char *drv_path, + struct job *parent) { struct job *job; int ret = 0; @@ -264,6 +311,18 @@ int job_new(struct job **j, char *name, char *drv_path) return -errno; } + job->outputs_size = 0; + job->outputs_filled = 0; + job->outputs = NULL; + + job->deps_size = 0; + job->deps_filled = 0; + job->deps = NULL; + + job->parents_size = 0; + job->parents_filled = 0; + job->parents = NULL; + if (name != NULL) { job->name = strdup(name); if (job->name == NULL) { @@ -282,14 +341,15 @@ int job_new(struct job **j, char *name, char *drv_path) goto out_free_name; } - job->outputs_size = 0; - job->outputs_filled = 0; - job->outputs = NULL; - - job->deps_size = 0; - job->deps_filled = 0; - job->deps = NULL; + if (parent != NULL) { + ret = job_parents_list_insert(job, parent); + if (ret < 0) + goto out_free_drv_path; + } +out_free_drv_path: + if (ret < 0) + free(job->drv_path); out_free_name: if (ret < 0) free(job->name); |