diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/evanix.c | 51 | ||||
-rw-r--r-- | src/jobs.c | 32 | ||||
-rw-r--r-- | src/meson.build | 9 | ||||
-rw-r--r-- | src/nix.c | 42 | ||||
-rw-r--r-- | src/solver_highs.c | 14 |
5 files changed, 126 insertions, 22 deletions
diff --git a/src/evanix.c b/src/evanix.c index 92f9596..25bbd8e 100644 --- a/src/evanix.c +++ b/src/evanix.c @@ -1,10 +1,12 @@ #include <errno.h> #include <getopt.h> +#include <nix/nix_api_value.h> #include <stdlib.h> #include <string.h> #include "build.h" #include "evanix.h" +#include "nix.h" #include "queue.h" #include "solver_conformity.h" #include "solver_highs.h" @@ -52,6 +54,8 @@ static int evanix(char *expr); static int evanix_free(struct evanix_opts_t *opts); static int opts_read(struct evanix_opts_t *opts, char **expr, int argc, char *argv[]); +static int evanix_opts_system_set(struct evanix_opts_t *opts, + nix_c_context *nix_ctx); /* This function returns errno on failure, consistent with the POSIX threads * functions, rather than returning -errno. */ @@ -71,13 +75,42 @@ static int evanix_build_thread_create(struct build_thread *build_thread) return 0; } +static int evanix_opts_system_set(struct evanix_opts_t *opts, + nix_c_context *nix_ctx) +{ + nix_err nix_ret; + + if (opts->system) + return 0; + + nix_ret = nix_setting_get(nix_ctx, "system", _nix_get_string_strdup, + &opts->system); + if (nix_ret != NIX_OK) { + print_err("%s", nix_err_msg(NULL, nix_ctx, NULL)); + return -EPERM; + } else if (opts->system == NULL) { + return -EPERM; + } + + return 0; +} + static int evanix(char *expr) { + nix_c_context *nix_ctx = NULL; struct queue_thread *queue_thread = NULL; struct build_thread *build_thread = NULL; FILE *jobs_stream = NULL; /* nix-eval-jobs stdout */ int ret = 0; + ret = _nix_init(&nix_ctx); + if (ret < 0) + goto out_free; + + ret = evanix_opts_system_set(&evanix_opts, nix_ctx); + if (ret < 0) + goto out_free; + ret = jobs_init(&jobs_stream, expr); if (ret < 0) goto out_free; @@ -127,6 +160,7 @@ static int evanix(char *expr) } out_free: + nix_c_context_free(nix_ctx); fclose(jobs_stream); queue_thread_free(queue_thread); free(build_thread); @@ -182,7 +216,13 @@ static int opts_read(struct evanix_opts_t *opts, char **expr, int argc, opts->isdryrun = true; break; case 's': - opts->system = optarg; + opts->system = strdup(optarg); + if (opts->system == NULL) { + print_err("%s", strerror(errno)); + ret = -errno; + goto out_free_evanix; + } + break; case 'r': opts->solver_report = true; @@ -194,7 +234,8 @@ static int opts_read(struct evanix_opts_t *opts, char **expr, int argc, "Try 'evanix --help' for more " "information.\n", c); - return -EINVAL; + ret = -EINVAL; + goto out_free_evanix; } ret = sqlite3_open_v2(optarg, &opts->statistics.db, @@ -212,7 +253,8 @@ static int opts_read(struct evanix_opts_t *opts, char **expr, int argc, NULL); if (ret != SQLITE_OK) { print_err("%s", "Failed to prepare sql"); - return -EPERM; + ret = -EPERM; + goto out_free_evanix; } break; @@ -351,11 +393,12 @@ static int evanix_free(struct evanix_opts_t *opts) { int ret; + free(opts->system); + if (opts->statistics.statement) { sqlite3_finalize(opts->statistics.statement); opts->statistics.statement = NULL; } - if (opts->statistics.db) { ret = sqlite3_close(opts->statistics.db); if (ret != SQLITE_OK) { @@ -12,11 +12,12 @@ #include "jobs.h" #include "util.h" +#define NIX_STORE_PATH "/nix/store/" + #ifndef NIX_EVAL_JOBS_PATH #warning "NIX_EVAL_JOBS_PATH not defined, evanix will rely on PATH instead" #define NIX_EVAL_JOBS_PATH nix - eval - jobs #endif - #define XSTR(x) STR(x) #define STR(x) #x #pragma message "NIX_EVAL_JOBS_PATH=" XSTR(NIX_EVAL_JOBS_PATH) @@ -224,6 +225,9 @@ int job_cost(struct job *job) int ret; char *pname; + if (job->insubstituters) + return 0; + if (!evanix_opts.max_time) return 1; @@ -419,14 +423,20 @@ static int job_read_cache(struct job *job) nlines = 0; for (bool in_fetched_block = false; getline(&line, &n, nix_build_stream) >= 0; nlines++) { + trimmed = trim(line); + if (strstr(line, "will be built")) { continue; } else if (strstr(line, "will be fetched")) { in_fetched_block = true; continue; + } else if (strncmp(trimmed, NIX_STORE_PATH, + sizeof(NIX_STORE_PATH) - 1)) { + /* TODO: use libstore instead + * */ + continue; } - trimmed = trim(line); j = job_search(job, trimmed); if (j == NULL) { ret = job_new(&dep_job, NULL, trimmed, NULL, job); @@ -498,16 +508,14 @@ int job_read(FILE *stream, struct job **job) goto out_free; } - if (evanix_opts.system != NULL) { - temp = cJSON_GetObjectItemCaseSensitive(root, "system"); - if (!cJSON_IsString(temp)) { - ret = JOB_READ_JSON_INVAL; - goto out_free; - } - if (strcmp(evanix_opts.system, temp->valuestring)) { - ret = JOB_READ_SYS_MISMATCH; - goto out_free; - } + temp = cJSON_GetObjectItemCaseSensitive(root, "system"); + if (!cJSON_IsString(temp)) { + ret = JOB_READ_JSON_INVAL; + goto out_free; + } + if (strcmp(evanix_opts.system, temp->valuestring)) { + ret = JOB_READ_SYS_MISMATCH; + goto out_free; } temp = cJSON_GetObjectItemCaseSensitive(root, "name"); diff --git a/src/meson.build b/src/meson.build index 03f045b..8a4158a 100644 --- a/src/meson.build +++ b/src/meson.build @@ -11,10 +11,17 @@ e = executable( 'solver_conformity.c', 'solver_highs.c', 'solver_sjf.c', + 'nix.c', + ], + + dependencies: [ + cjson_dep, + highs_dep, + sqlite_dep, + nix_store_dep ], include_directories: evanix_inc, - dependencies: [ cjson_dep, highs_dep, sqlite_dep ], install: true, c_args: [f'-DNIX_EVAL_JOBS_PATH=@NIX_EVAL_JOBS_PATH@'], ) diff --git a/src/nix.c b/src/nix.c new file mode 100644 index 0000000..f1b3a5a --- /dev/null +++ b/src/nix.c @@ -0,0 +1,42 @@ +#include <errno.h> +#include <string.h> + +#include "nix.h" +#include "util.h" + +void _nix_get_string_strdup(const char *str, unsigned n, void *user_data) +{ + char **s = user_data; + + *s = strndup(str, n); + if (*s == NULL) + print_err("%s", strerror(errno)); +} + +int _nix_init(nix_c_context **nix_ctx) +{ + nix_err nix_ret; + nix_c_context *nc; + int ret = 0; + + nc = nix_c_context_create(); + if (nix_ctx == NULL) { + print_err("%s", "Failed to create nix context"); + return -EPERM; + } + + nix_ret = nix_libstore_init(nc); + if (nix_ret != NIX_OK) { + print_err("%s", nix_err_msg(NULL, nc, NULL)); + ret = -EPERM; + goto out_free_nc; + } + +out_free_nc: + if (ret < 0) + nix_c_context_free(nc); + else + *nix_ctx = nc; + + return ret; +} diff --git a/src/solver_highs.c b/src/solver_highs.c index e3b6a1f..b641e54 100644 --- a/src/solver_highs.c +++ b/src/solver_highs.c @@ -14,6 +14,7 @@ static int solver_highs_unwrapped(double *solution, struct job_clist *q, { HighsInt precedence_index[2]; double precedence_value[2]; + int num_non_zero; struct job *j; int ret; @@ -80,24 +81,27 @@ static int solver_highs_unwrapped(double *solution, struct job_clist *q, ret = -errno; goto out_free_col_profit; } - for (size_t i = 0; i < jobid->filled; i++) - constraint_index[i] = i; - constraint_value = malloc(jobid->filled * sizeof(*constraint_value)); if (constraint_value == NULL) { print_err("%s", strerror(errno)); ret = -errno; goto out_free_col_profit; } + + num_non_zero = 0; for (size_t i = 0; i < jobid->filled; i++) { ret = job_cost(jobid->jobs[i]); if (ret < 0) return ret; + else if (ret == 0) + continue; - constraint_value[i] = ret; + constraint_value[num_non_zero] = ret; + constraint_index[num_non_zero] = i; + num_non_zero++; } - ret = Highs_addRow(highs, 0, resources, jobid->filled, constraint_index, + ret = Highs_addRow(highs, 0, resources, num_non_zero, constraint_index, constraint_value); if (ret != kHighsStatusOk) { print_err("%s", "highs did not return kHighsStatusOk"); |