#include <stdio.h> #include <assert.h> #include <mysql.h> #include "mx_log.h" #include "mxq_group.h" #include "mxq_job.h" #include "mx_util.h" #include "mx_mysql.h" #define GROUP_FIELDS_CNT 36 #define GROUP_FIELDS \ " group_id," \ " group_name," \ " group_status," \ " group_flags," \ " group_priority," \ " group_blacklist," \ " group_whitelist," \ " prerequisites," \ " tags," \ " user_uid," \ " user_name," \ " user_gid," \ " user_group," \ " job_command," \ " job_threads," \ " job_memory," \ " job_time," \ " job_tmpdir_size," \ " job_max_per_node," \ " job_gpu," \ " group_jobs," \ " group_jobs_inq," \ " group_jobs_running," \ " group_jobs_finished," \ " group_jobs_failed," \ " group_jobs_cancelled," \ " group_jobs_unknown," \ " group_slots_running," \ " stats_max_sumrss," \ " stats_max_maxrss," \ " stats_max_utime_sec," \ " stats_max_stime_sec," \ " stats_max_real_sec," \ " stats_wait_sec," \ " stats_run_sec," \ " stats_idle_sec" static void bind_result_group_fields(struct mx_mysql_bind *result, struct mxq_group *g) { int idx = 0; mx_mysql_bind_init_result(result, GROUP_FIELDS_CNT); mx_mysql_bind_var(result, idx++, uint64, &(g->group_id)); mx_mysql_bind_var(result, idx++, string, &(g->group_name)); mx_mysql_bind_var(result, idx++, uint8, &(g->group_status)); mx_mysql_bind_var(result, idx++, uint64, &(g->group_flags)); mx_mysql_bind_var(result, idx++, uint16, &(g->group_priority)); mx_mysql_bind_var(result, idx++, string, &(g->group_blacklist)); mx_mysql_bind_var(result, idx++, string, &(g->group_whitelist)); mx_mysql_bind_var(result, idx++, string, &(g->prerequisites)); mx_mysql_bind_var(result, idx++, string, &(g->tags)); mx_mysql_bind_var(result, idx++, uint32, &(g->user_uid)); mx_mysql_bind_var(result, idx++, string, &(g->user_name)); mx_mysql_bind_var(result, idx++, uint32, &(g->user_gid)); mx_mysql_bind_var(result, idx++, string, &(g->user_group)); mx_mysql_bind_var(result, idx++, string, &(g->job_command)); mx_mysql_bind_var(result, idx++, uint16, &(g->job_threads)); mx_mysql_bind_var(result, idx++, uint64, &(g->job_memory)); mx_mysql_bind_var(result, idx++, uint32, &(g->job_time)); mx_mysql_bind_var(result, idx++, uint32, &(g->job_tmpdir_size)); mx_mysql_bind_var(result, idx++, uint16, &(g->job_max_per_node)); mx_mysql_bind_var(result, idx++, uint16, &(g->job_gpu)); mx_mysql_bind_var(result, idx++, uint64, &(g->group_jobs)); mx_mysql_bind_var(result, idx++, uint64, &(g->group_jobs_inq)); mx_mysql_bind_var(result, idx++, uint64, &(g->group_jobs_running)); mx_mysql_bind_var(result, idx++, uint64, &(g->group_jobs_finished)); mx_mysql_bind_var(result, idx++, uint64, &(g->group_jobs_failed)); mx_mysql_bind_var(result, idx++, uint64, &(g->group_jobs_cancelled)); mx_mysql_bind_var(result, idx++, uint64, &(g->group_jobs_unknown)); mx_mysql_bind_var(result, idx++, uint64, &(g->group_slots_running)); mx_mysql_bind_var(result, idx++, uint64, &(g->stats_max_sumrss)); mx_mysql_bind_var(result, idx++, uint64, &(g->stats_max_maxrss)); mx_mysql_bind_var(result, idx++, int64, &(g->stats_max_utime.tv_sec)); mx_mysql_bind_var(result, idx++, int64, &(g->stats_max_stime.tv_sec)); mx_mysql_bind_var(result, idx++, int64, &(g->stats_max_real.tv_sec)); mx_mysql_bind_var(result, idx++, uint64, &(g->stats_wait_sec)); mx_mysql_bind_var(result, idx++, uint64, &(g->stats_run_sec)); mx_mysql_bind_var(result, idx++, uint64, &(g->stats_idle_sec)); } void mxq_group_free_content(struct mxq_group *g) { mx_free_null(g->prerequisites); mx_free_null(g->tags); mx_free_null(g->group_whitelist); mx_free_null(g->group_blacklist); mx_free_null(g->group_name); mx_free_null(g->user_name); mx_free_null(g->user_group); mx_free_null(g->job_command); } static uint64_t mxq_group_jobs_done(struct mxq_group *g) { uint64_t done = 0; done += g->group_jobs_finished; done += g->group_jobs_failed; done += g->group_jobs_cancelled; done += g->group_jobs_unknown; return done; } uint64_t mxq_group_jobs_active(struct mxq_group *g) { uint64_t active; active = g->group_jobs; active -= mxq_group_jobs_done(g); if (active != g->group_jobs_inq+g->group_jobs_running) mx_log_warning("BUG: mxq_group: inconsistent 'active'=%lu (inq=%lu+run=%lu)=%lu value", active, g->group_jobs_inq, g->group_jobs_running, g->group_jobs_inq+g->group_jobs_running); return active; } uint64_t mxq_group_jobs_inq(struct mxq_group *g) { uint64_t inq; inq = mxq_group_jobs_active(g); inq -= g->group_jobs_running; if (inq != g->group_jobs_inq) mx_log_warning("BUG: mxq_group: inconsistent inq value (%lu != %lu)", inq, g->group_jobs_inq); return inq; } int mxq_load_group(struct mx_mysql *mysql, struct mxq_group **mxq_groups, uint64_t group_id) { int res; struct mxq_group *groups = NULL; struct mxq_group g = {0}; struct mx_mysql_bind param = {0}; struct mx_mysql_bind result = {0}; assert(mysql); assert(mxq_groups); assert(!(*mxq_groups)); char *query = "SELECT" GROUP_FIELDS " FROM mxq_group" " WHERE group_id = ?" " LIMIT 1"; mx_mysql_bind_init_param(¶m, 1); mx_mysql_bind_var(¶m, 0, uint64, &group_id); bind_result_group_fields(&result, &g); res = mx_mysql_do_statement(mysql, query, ¶m, &result, &g, (void **)&groups, sizeof(*groups)); if (res < 0) { mx_log_err("mx_mysql_do_statement(): %s", mx_mysql_error()); return res; } *mxq_groups = groups; return res; } int mxq_load_all_groups(struct mx_mysql *mysql, struct mxq_group **mxq_groups) { int res; struct mxq_group *groups = NULL; struct mxq_group g = {0}; struct mx_mysql_bind result = {0}; assert(mysql); assert(mxq_groups); assert(!(*mxq_groups)); char *query = "SELECT" GROUP_FIELDS " FROM mxq_group" " ORDER BY user_name, group_mtime"; bind_result_group_fields(&result, &g); res = mx_mysql_do_statement(mysql, query, NULL, &result, &g, (void **)&groups, sizeof(*groups)); if (res < 0) { mx_log_err("mx_mysql_do_statement(): %s", mx_mysql_error()); return res; } *mxq_groups = groups; return res; } int mxq_load_all_groups_for_user(struct mx_mysql *mysql, struct mxq_group **mxq_groups, uint64_t user_uid) { int res; struct mxq_group *groups = NULL; struct mxq_group g = {0}; struct mx_mysql_bind param = {0}; struct mx_mysql_bind result = {0}; assert(mysql); assert(mxq_groups); assert(!(*mxq_groups)); char *query = "SELECT" GROUP_FIELDS " FROM mxq_group" " WHERE user_uid = ?" " ORDER BY user_name, group_mtime"; mx_mysql_bind_init_param(¶m, 1); mx_mysql_bind_var(¶m, 0, uint64, &user_uid); bind_result_group_fields(&result, &g); res = mx_mysql_do_statement(mysql, query, ¶m, &result, &g, (void **)&groups, sizeof(*groups)); if (res < 0) { mx_log_err("mx_mysql_do_statement(): %s", mx_mysql_error()); return res; } *mxq_groups = groups; return res; } int mxq_load_active_groups_for_user(struct mx_mysql *mysql, struct mxq_group **mxq_groups, uint64_t user_uid) { int res; struct mxq_group *groups = NULL; struct mxq_group g = {0}; struct mx_mysql_bind result = {0}; struct mx_mysql_bind param = {0}; assert(mysql); assert(mxq_groups); assert(!(*mxq_groups)); char *query = "SELECT" GROUP_FIELDS " FROM mxq_group" " WHERE ((group_jobs_inq > 0 OR group_jobs_running > 0)" " OR (NOW()-group_date_end < 86400))" " AND user_uid = ?" " ORDER BY user_name, group_mtime"; mx_mysql_bind_init_param(¶m, 1); mx_mysql_bind_var(¶m, 0, uint64, &user_uid); bind_result_group_fields(&result, &g); res = mx_mysql_do_statement(mysql, query, ¶m, &result, &g, (void **)&groups, sizeof(*groups)); if (res < 0) { mx_log_err("mx_mysql_do_statement(): %s", mx_mysql_error()); return res; } *mxq_groups = groups; return res; } int mxq_load_running_groups(struct mx_mysql *mysql, struct mxq_group **mxq_groups) { int res; struct mxq_group *groups = NULL; struct mxq_group g = {0}; struct mx_mysql_bind result = {0}; assert(mysql); assert(mxq_groups); assert(!(*mxq_groups)); char *query = "SELECT" GROUP_FIELDS " FROM mxq_group" " WHERE (group_jobs_inq > 0 OR group_jobs_running > 0)" " ORDER BY user_name, group_mtime"; bind_result_group_fields(&result, &g); res = mx_mysql_do_statement(mysql, query, NULL, &result, &g, (void **)&groups, sizeof(*groups)); if (res < 0) { mx_log_err("mx_mysql_do_statement(): %s", mx_mysql_error()); return res; } *mxq_groups = groups; return res; } int mxq_load_running_groups_for_user(struct mx_mysql *mysql, struct mxq_group **mxq_groups, uint64_t user_uid) { int res; struct mxq_group *groups = NULL; struct mxq_group g = {0}; struct mx_mysql_bind param = {0}; struct mx_mysql_bind result = {0}; assert(mysql); assert(mxq_groups); assert(!(*mxq_groups)); char *query = "SELECT" GROUP_FIELDS " FROM mxq_group" " WHERE (group_jobs_inq > 0 OR group_jobs_running > 0)" " AND user_uid = ?" " ORDER BY user_name, group_mtime"; mx_mysql_bind_init_param(¶m, 1); mx_mysql_bind_var(¶m, 0, uint64, &user_uid); bind_result_group_fields(&result, &g); res = mx_mysql_do_statement(mysql, query, ¶m, &result, &g, (void **)&groups, sizeof(*groups)); if (res < 0) { mx_log_err("mx_mysql_do_statement(): %s", mx_mysql_error()); return res; } *mxq_groups = groups; return res; }