Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
mxq/mxq_job.c
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
796 lines (668 sloc)
24.6 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _GNU_SOURCE | |
#include <stdio.h> | |
#include <mysql.h> | |
#include <errno.h> | |
#include <assert.h> | |
#include <unistd.h> | |
#include <libgen.h> | |
#include <string.h> | |
#include <sys/resource.h> | |
#include "mx_util.h" | |
#include "mx_log.h" | |
#include "mx_util.h" | |
#include "mxq_daemon.h" | |
#include "mxq_group.h" | |
#include "mxq_job.h" | |
#define JOB_FIELDS_CNT 37 | |
#define JOB_FIELDS \ | |
" job_id, " \ | |
" job_status, " \ | |
" job_priority, " \ | |
" group_id, " \ | |
" job_workdir, " \ | |
" job_argc, " \ | |
" job_argv, " \ | |
" job_stdout, " \ | |
" job_stderr, " \ | |
" job_umask, " \ | |
" host_submit, " \ | |
" host_id, " \ | |
" daemon_id, " \ | |
" server_id, " \ | |
" host_hostname, " \ | |
" host_pid, " \ | |
" host_slots, " \ | |
" host_cpu_set, " \ | |
" UNIX_TIMESTAMP(date_submit) as date_submit, " \ | |
" UNIX_TIMESTAMP(date_start) as date_start, " \ | |
" UNIX_TIMESTAMP(date_end) as date_end, " \ | |
" stats_max_sumrss, " \ | |
" stats_status, " \ | |
" stats_utime_sec, " \ | |
" stats_utime_usec, " \ | |
" stats_stime_sec, " \ | |
" stats_stime_usec, " \ | |
" stats_real_sec, " \ | |
" stats_real_usec, " \ | |
" stats_maxrss, " \ | |
" stats_minflt, " \ | |
" stats_majflt, " \ | |
" stats_nswap, " \ | |
" stats_inblock, " \ | |
" stats_oublock, " \ | |
" stats_nvcsw, " \ | |
" stats_nivcsw" | |
static void bind_result_job_fields(struct mx_mysql_bind *result, struct mxq_job *j) | |
{ | |
int idx = 0; | |
mx_mysql_bind_init_result(result, JOB_FIELDS_CNT); | |
mx_mysql_bind_var(result, idx++, uint64, &(j->job_id)); | |
mx_mysql_bind_var(result, idx++, uint16, &(j->job_status)); | |
mx_mysql_bind_var(result, idx++, uint16, &(j->job_priority)); | |
mx_mysql_bind_var(result, idx++, uint64, &(j->group_id)); | |
mx_mysql_bind_var(result, idx++, string, &(j->job_workdir)); | |
mx_mysql_bind_var(result, idx++, uint32, &(j->job_argc)); | |
mx_mysql_bind_var(result, idx++, string, &(j->job_argv_str)); | |
mx_mysql_bind_var(result, idx++, string, &(j->job_stdout)); | |
mx_mysql_bind_var(result, idx++, string, &(j->job_stderr)); | |
mx_mysql_bind_var(result, idx++, uint32, &(j->job_umask)); | |
mx_mysql_bind_var(result, idx++, string, &(j->host_submit)); | |
mx_mysql_bind_var(result, idx++, string, &(j->host_id)); | |
mx_mysql_bind_var(result, idx++, uint32, &(j->daemon_id)); | |
mx_mysql_bind_var(result, idx++, string, &(j->daemon_name)); | |
mx_mysql_bind_var(result, idx++, string, &(j->host_hostname)); | |
mx_mysql_bind_var(result, idx++, uint32, &(j->host_pid)); | |
mx_mysql_bind_var(result, idx++, uint32, &(j->host_slots)); | |
mx_mysql_bind_var(result, idx++, string, &(j->host_cpu_set_str)); | |
mx_mysql_bind_var(result, idx++, int64, &(j->date_submit)); | |
mx_mysql_bind_var(result, idx++, int64, &(j->date_start)); | |
mx_mysql_bind_var(result, idx++, int64, &(j->date_end)); | |
mx_mysql_bind_var(result, idx++, uint64, &(j->stats_max_sumrss)); | |
mx_mysql_bind_var(result, idx++, int32, &(j->stats_status)); | |
mx_mysql_bind_var(result, idx++, int64, &(j->stats_rusage.ru_utime.tv_sec)); | |
mx_mysql_bind_var(result, idx++, int64, &(j->stats_rusage.ru_utime.tv_usec)); | |
mx_mysql_bind_var(result, idx++, int64, &(j->stats_rusage.ru_stime.tv_sec)); | |
mx_mysql_bind_var(result, idx++, int64, &(j->stats_rusage.ru_stime.tv_usec)); | |
mx_mysql_bind_var(result, idx++, int64, &(j->stats_realtime.tv_sec)); | |
mx_mysql_bind_var(result, idx++, int64, &(j->stats_realtime.tv_usec)); | |
mx_mysql_bind_var(result, idx++, int64, &(j->stats_rusage.ru_maxrss)); | |
mx_mysql_bind_var(result, idx++, int64, &(j->stats_rusage.ru_minflt)); | |
mx_mysql_bind_var(result, idx++, int64, &(j->stats_rusage.ru_majflt)); | |
mx_mysql_bind_var(result, idx++, int64, &(j->stats_rusage.ru_nswap)); | |
mx_mysql_bind_var(result, idx++, int64, &(j->stats_rusage.ru_inblock)); | |
mx_mysql_bind_var(result, idx++, int64, &(j->stats_rusage.ru_oublock)); | |
mx_mysql_bind_var(result, idx++, int64, &(j->stats_rusage.ru_nvcsw)); | |
mx_mysql_bind_var(result, idx++, int64, &(j->stats_rusage.ru_nivcsw)); | |
} | |
char *mxq_job_status_to_name(uint64_t status) | |
{ | |
switch (status) { | |
case MXQ_JOB_STATUS_INQ: | |
return "inq"; | |
case MXQ_JOB_STATUS_ASSIGNED: | |
return "assigned"; | |
case MXQ_JOB_STATUS_LOADED: | |
return "loaded"; | |
case MXQ_JOB_STATUS_RUNNING: | |
return "running"; | |
case MXQ_JOB_STATUS_KILLED: | |
return "killed"; | |
case MXQ_JOB_STATUS_FAILED: | |
return "failed"; | |
case MXQ_JOB_STATUS_CANCELLED: | |
return "cancelled"; | |
case MXQ_JOB_STATUS_UNKNOWN: | |
return "unknown"; | |
case MXQ_JOB_STATUS_FINISHED: | |
return "finished"; | |
} | |
return "invalid"; | |
} | |
void mxq_job_free_content(struct mxq_job *j) | |
{ | |
mx_free_null(j->job_workdir); | |
mx_free_null(j->job_argv); | |
mx_free_null(j->job_argv_str); | |
mx_free_null(j->job_stdout); | |
mx_free_null(j->job_stderr); | |
if (j->tmp_stderr == j->tmp_stdout) { | |
j->tmp_stdout = NULL; | |
} else { | |
mx_free_null(j->tmp_stdout); | |
} | |
mx_free_null(j->tmp_stderr); | |
mx_free_null(j->host_submit); | |
mx_free_null(j->host_id); | |
mx_free_null(j->daemon_name); | |
mx_free_null(j->host_hostname); | |
mx_free_null(j->host_cpu_set_str); | |
} | |
static int do_jobs_statement(struct mx_mysql *mysql, char *query, struct mx_mysql_bind *param, struct mxq_job **jobs) | |
{ | |
int res,i; | |
struct mxq_job j = {0}; | |
struct mx_mysql_bind result = {0}; | |
bind_result_job_fields(&result, &j); | |
res = mx_mysql_do_statement(mysql, query, param, &result, &j, (void **)jobs, sizeof(**jobs)); | |
if (res < 0) { | |
mx_log_err("mx_mysql_do_statement(): %s", mx_mysql_error()); | |
return res; | |
} | |
for (i=0;i<res;i++) | |
mx_str_to_cpuset(&(*jobs)[i].host_cpu_set,(*jobs)[i].host_cpu_set_str); | |
return res; | |
} | |
int mxq_load_job(struct mx_mysql *mysql, struct mxq_job **jobs_result, uint64_t job_id) | |
{ | |
struct mxq_job *jobs_tmp = NULL; | |
struct mx_mysql_bind param = {0}; | |
int idx; | |
int res; | |
assert(mysql); | |
assert(jobs_result); | |
assert(!(*jobs_result)); | |
char *query = | |
"SELECT" | |
JOB_FIELDS | |
" FROM" | |
" mxq_job" | |
" WHERE job_id = ?" | |
" LIMIT 1"; | |
mx_mysql_bind_init_param(¶m, 1); | |
idx = 0; | |
mx_mysql_bind_var(¶m, idx++, uint64, &job_id); | |
res = do_jobs_statement(mysql, query, ¶m, &jobs_tmp); | |
if (res >= 0) | |
*jobs_result = jobs_tmp; | |
return res; | |
} | |
int mxq_load_jobs_in_group(struct mx_mysql *mysql, struct mxq_job **jobs_result, struct mxq_group *grp) | |
{ | |
int res; | |
struct mxq_job *jobs_tmp = NULL; | |
struct mx_mysql_bind param = {0}; | |
assert(mysql); | |
assert(jobs_result); | |
assert(!(*jobs_result)); | |
char *query = | |
"SELECT" | |
JOB_FIELDS | |
" FROM mxq_job" | |
" WHERE group_id = ? OR 1 = 0" | |
" ORDER BY server_id, host_hostname, job_id"; | |
mx_mysql_bind_init_param(¶m, 1); | |
mx_mysql_bind_var(¶m, 0, uint64, &(grp->group_id)); | |
res = do_jobs_statement(mysql, query, ¶m, &jobs_tmp); | |
if (res >= 0) | |
*jobs_result = jobs_tmp; | |
return res; | |
} | |
int mxq_load_jobs_in_group_with_status(struct mx_mysql *mysql, struct mxq_job **jobs_result, struct mxq_group *grp, uint64_t job_status) | |
{ | |
struct mxq_job *jobs_tmp = NULL; | |
struct mx_mysql_bind param = {0}; | |
int idx; | |
int res; | |
assert(mysql); | |
assert(jobs_result); | |
assert(!(*jobs_result)); | |
char *query = | |
"SELECT" | |
JOB_FIELDS | |
" FROM" | |
" mxq_job" | |
" WHERE group_id = ?" | |
" AND job_status = ?" | |
" ORDER BY" | |
" server_id," | |
" host_hostname," | |
" job_id"; | |
mx_mysql_bind_init_param(¶m, 2); | |
idx = 0; | |
mx_mysql_bind_var(¶m, idx++, uint64, &(grp->group_id)); | |
mx_mysql_bind_var(¶m, idx++, uint64, &job_status); | |
res = do_jobs_statement(mysql, query, ¶m, &jobs_tmp); | |
if (res >= 0) | |
*jobs_result = jobs_tmp; | |
return res; | |
} | |
static uint64_t mxq_select_job_from_group(struct mx_mysql *mysql, uint64_t group_id) | |
{ | |
struct mx_mysql_bind param = {0}; | |
struct mx_mysql_bind result = {0}; | |
uint64_t job_id; | |
uint64_t *job_id_out = NULL; | |
int res; | |
char *query = | |
"SELECT" | |
" job_id" | |
" FROM" | |
" mxq_job" | |
" WHERE group_id = ?" | |
" AND job_status = " status_str(MXQ_JOB_STATUS_INQ) | |
" AND daemon_id = 0" | |
" AND host_hostname = ''" | |
" AND server_id = ''" | |
" AND host_pid = 0" | |
" ORDER BY" | |
" job_priority," | |
" job_id" | |
" LIMIT 1"; | |
mx_mysql_bind_init_param(¶m, 1); | |
mx_mysql_bind_var(¶m,0, uint64, &group_id); | |
mx_mysql_bind_init_result(&result, 1); | |
mx_mysql_bind_var(&result,0,uint64,&job_id); | |
res = mx_mysql_do_statement(mysql, query, ¶m, &result, &job_id, (void **)&job_id_out,sizeof(*job_id_out)); | |
if (res==1) { | |
job_id=job_id_out[0]; | |
} else { | |
job_id=0; | |
} | |
if (job_id_out) | |
free(job_id_out); | |
return(job_id); | |
} | |
static int mxq_assign_job_from_group_to_daemon(struct mx_mysql *mysql, uint64_t group_id, struct mxq_daemon *daemon, unsigned long slots_per_job) | |
{ | |
struct mx_mysql_bind param = {0}; | |
int res; | |
int idx; | |
uint64_t job_id; | |
assert(mysql); | |
assert(daemon); | |
assert(daemon->hostname); | |
assert(*daemon->hostname); | |
assert(daemon->daemon_name); | |
assert(*daemon->daemon_name); | |
assert(daemon->daemon_id); | |
char *query = | |
"UPDATE " | |
" mxq_job" | |
" SET" | |
" daemon_id = ?," | |
" host_hostname = ?," | |
" host_slots = ?, " | |
" server_id = ?," | |
" job_status = " status_str(MXQ_JOB_STATUS_ASSIGNED) | |
" WHERE job_id = ?" | |
" AND job_status = " status_str(MXQ_JOB_STATUS_INQ); | |
job_id=mxq_select_job_from_group(mysql,group_id); | |
if (!job_id) { | |
return(0); | |
} | |
mx_mysql_bind_init_param(¶m, 5); | |
idx = 0; | |
mx_mysql_bind_var(¶m, idx++, uint32, &daemon->daemon_id); | |
mx_mysql_bind_var(¶m, idx++, string, &daemon->hostname); | |
mx_mysql_bind_var(¶m, idx++, uint64, &slots_per_job); | |
mx_mysql_bind_var(¶m, idx++, string, &daemon->daemon_name); | |
mx_mysql_bind_var(¶m, idx++, uint64, &job_id); | |
res = mx_mysql_do_statement_noresult(mysql, query, ¶m); | |
if (res < 0) | |
mx_log_err("mx_mysql_do_statement(): %s", mx_mysql_error()); | |
return res; | |
} | |
int mxq_unassign_jobs_of_server(struct mx_mysql *mysql, struct mxq_daemon *daemon) | |
{ | |
struct mx_mysql_bind param = {0}; | |
int res; | |
int idx; | |
assert(mysql); | |
assert(daemon->hostname); | |
assert(daemon->daemon_name); | |
assert(*daemon->hostname); | |
assert(*daemon->daemon_name); | |
char *query = | |
"UPDATE" | |
" mxq_job" | |
" SET" | |
" daemon_id = 0," | |
" host_hostname = ''," | |
" host_slots = 0," | |
" server_id = ''," | |
" job_status = " status_str(MXQ_JOB_STATUS_INQ) | |
" WHERE job_status = " status_str(MXQ_JOB_STATUS_ASSIGNED) | |
" AND host_pid = 0" | |
" AND host_hostname = ?" | |
" AND server_id = ?"; | |
mx_mysql_bind_init_param(¶m, 2); | |
idx = 0; | |
mx_mysql_bind_var(¶m, idx++, string, &daemon->hostname); | |
mx_mysql_bind_var(¶m, idx++, string, &daemon->daemon_name); | |
res = mx_mysql_do_statement_noresult_retry_on_fail(mysql, query, ¶m); | |
if (res < 0) { | |
mx_log_err("mx_mysql_do_statement(): %s", mx_mysql_error()); | |
return res; | |
} | |
return res; | |
} | |
static int mxq_set_job_status_loaded_on_server(struct mx_mysql *mysql, struct mxq_job *job) | |
{ | |
struct mx_mysql_bind param = {0}; | |
int res; | |
int idx; | |
assert(mysql); | |
assert(job); | |
assert(job->job_id); | |
assert(job->daemon_id); | |
char *host_id = mx_asprintf_forever("%u", job->daemon_id); | |
char *query = | |
"UPDATE" | |
" mxq_job" | |
" SET" | |
" host_id = ?," | |
" job_status = " status_str(MXQ_JOB_STATUS_LOADED) | |
" WHERE job_status = " status_str(MXQ_JOB_STATUS_ASSIGNED) | |
" AND job_id = ?" | |
" AND daemon_id = ?" | |
" AND host_pid = 0"; | |
mx_mysql_bind_init_param(¶m, 3); | |
idx = 0; | |
mx_mysql_bind_var(¶m, idx++, string, &host_id); | |
mx_mysql_bind_var(¶m, idx++, uint64, &(job->job_id)); | |
mx_mysql_bind_var(¶m, idx++, uint32, &(job->daemon_id)); | |
res = mx_mysql_do_statement_noresult_retry_on_fail(mysql, query, ¶m); | |
if (res < 0) { | |
mx_log_err("mx_mysql_do_statement(): %s", mx_mysql_error()); | |
return res; | |
} | |
mx_free_null(job->host_id); | |
job->host_id = host_id; | |
job->job_status = MXQ_JOB_STATUS_LOADED; | |
return res; | |
} | |
int mxq_set_job_status_running(struct mx_mysql *mysql, struct mxq_job *job) | |
{ | |
assert(mysql); | |
assert(job); | |
assert(job->job_id); | |
assert(job->daemon_id); | |
assert(job->host_pid); | |
assert(job->host_slots); | |
assert(job->host_cpu_set_str); | |
assert(*job->host_cpu_set_str); | |
struct mx_mysql_bind param = {0}; | |
int res; | |
int idx; | |
char *query = | |
"UPDATE" | |
" mxq_job" | |
" SET" | |
" host_pid = ?," | |
" host_slots = ?," | |
" host_cpu_set = ?," | |
" job_status = " status_str(MXQ_JOB_STATUS_RUNNING) | |
" WHERE job_status = " status_str(MXQ_JOB_STATUS_LOADED) | |
" AND job_id = ?" | |
" AND daemon_id = ?" | |
" AND host_pid = 0"; | |
mx_mysql_bind_init_param(¶m, 5); | |
idx = 0; | |
mx_mysql_bind_var(¶m, idx++, uint32, &(job->host_pid)); | |
mx_mysql_bind_var(¶m, idx++, uint32, &(job->host_slots)); | |
mx_mysql_bind_var(¶m, idx++, string, &(job->host_cpu_set_str)); | |
mx_mysql_bind_var(¶m, idx++, uint64, &(job->job_id)); | |
mx_mysql_bind_var(¶m, idx++, uint32, &(job->daemon_id)); | |
res = mx_mysql_do_statement_noresult_retry_on_fail(mysql, query, ¶m); | |
if (res < 0) { | |
mx_log_err("mx_mysql_do_statement(): %s", mx_mysql_error()); | |
return res; | |
} | |
job->job_status = MXQ_JOB_STATUS_RUNNING; | |
return res; | |
} | |
int mxq_set_job_status_exited(struct mx_mysql *mysql, struct mxq_job *job) | |
{ | |
int res; | |
int idx; | |
uint16_t newstatus; | |
struct mx_mysql_bind param = {0}; | |
assert(mysql); | |
assert(job); | |
assert(job->host_pid); | |
if (WIFEXITED(job->stats_status)) { | |
if (WEXITSTATUS(job->stats_status)) { | |
newstatus = MXQ_JOB_STATUS_FAILED; | |
} else { | |
newstatus = MXQ_JOB_STATUS_FINISHED; | |
} | |
} else if(WIFSIGNALED(job->stats_status)) { | |
newstatus = MXQ_JOB_STATUS_KILLED; | |
} else { | |
mx_log_err("Status change to status_exit called with unknown stats_status (%d). Aborting Status change.", job->stats_status); | |
errno = EINVAL; | |
return -1; | |
} | |
char *query = | |
"UPDATE" | |
" mxq_job" | |
" SET" | |
" stats_max_sumrss = ?," | |
" stats_status = ?," | |
" stats_utime_sec = ?," | |
" stats_utime_usec = ?," | |
" stats_stime_sec = ?," | |
" stats_stime_usec = ?," | |
" stats_real_sec = ?," | |
" stats_real_usec = ?," | |
" stats_maxrss = ?," | |
" stats_minflt = ?," | |
" stats_majflt = ?," | |
" stats_nswap = ?," | |
" stats_inblock = ?," | |
" stats_oublock = ?," | |
" stats_nvcsw = ?," | |
" stats_nivcsw = ?," | |
" job_status = ?," | |
" date_end = CURRENT_TIMESTAMP()" | |
" WHERE job_status IN (" | |
status_str(MXQ_JOB_STATUS_LOADED) "," | |
status_str(MXQ_JOB_STATUS_RUNNING) ")" | |
" AND job_id = ?" | |
" AND daemon_id = ?" | |
" AND host_pid = ?"; | |
mx_mysql_bind_init_param(¶m, 20); | |
idx = 0; | |
mx_mysql_bind_var(¶m, idx++, uint64, &(job->stats_max_sumrss)); | |
mx_mysql_bind_var(¶m, idx++, int32, &(job->stats_status)); | |
mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_utime.tv_sec)); | |
mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_utime.tv_usec)); | |
mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_stime.tv_sec)); | |
mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_stime.tv_usec)); | |
mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_realtime.tv_sec)); | |
mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_realtime.tv_usec)); | |
mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_maxrss)); | |
mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_minflt)); | |
mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_majflt)); | |
mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_nswap)); | |
mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_inblock)); | |
mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_oublock)); | |
mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_nvcsw)); | |
mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_nivcsw)); | |
mx_mysql_bind_var(¶m, idx++, uint16, &(newstatus)); | |
mx_mysql_bind_var(¶m, idx++, uint64, &(job->job_id)); | |
mx_mysql_bind_var(¶m, idx++, uint32, &(job->daemon_id)); | |
mx_mysql_bind_var(¶m, idx++, uint32, &(job->host_pid)); | |
res = mx_mysql_do_statement_noresult_retry_on_fail(mysql, query, ¶m); | |
if (res < 0) { | |
mx_log_err("mx_mysql_do_statement(): %s", mx_mysql_error()); | |
return res; | |
} | |
job->job_status = newstatus; | |
return res; | |
} | |
int mxq_set_job_status_unknown(struct mx_mysql *mysql, struct mxq_job *job) | |
{ | |
struct mx_mysql_bind param = {0}; | |
int idx; | |
int res; | |
char *query = | |
"UPDATE" | |
" mxq_job" | |
" SET" | |
" job_status = " status_str(MXQ_JOB_STATUS_UNKNOWN) | |
" WHERE job_id = ?"; | |
mx_mysql_bind_init_param(¶m, 1); | |
idx = 0; | |
mx_mysql_bind_var(¶m, idx++, uint64, &job->job_id); | |
res = mx_mysql_do_statement_noresult_retry_on_fail(mysql, query, ¶m); | |
if (res < 0) { | |
mx_log_err("mx_mysql_do_statement(): %s", mx_mysql_error()); | |
return res; | |
} | |
return res; | |
} | |
int mxq_job_set_tmpfilenames(struct mxq_group *g, struct mxq_job *j) | |
{ | |
if (!mx_streq(j->job_stdout, "/dev/null")) { | |
_mx_cleanup_free_ char *dir = NULL; | |
dir = mx_dirname_forever(j->job_stdout); | |
j->tmp_stdout = mx_asprintf_forever("%s/mxq.%u.%lu.%lu.%s.%s.%d.stdout.tmp", | |
dir, g->user_uid, g->group_id, j->job_id, j->host_hostname, | |
j->daemon_name, j->host_pid); | |
} | |
if (!mx_streq(j->job_stderr, "/dev/null")) { | |
_mx_cleanup_free_ char *dir = NULL; | |
if (mx_streq(j->job_stderr, j->job_stdout)) { | |
j->tmp_stderr = j->tmp_stdout; | |
return 1; | |
} | |
dir = mx_dirname_forever(j->job_stderr); | |
j->tmp_stderr = mx_asprintf_forever("%s/mxq.%u.%lu.%lu.%s.%s.%d.stderr.tmp", | |
dir, g->user_uid, g->group_id, j->job_id, j->host_hostname, | |
j->daemon_name, j->host_pid); | |
} | |
return 1; | |
} | |
static int mxq_load_job_from_group_assigned_to_daemon(struct mx_mysql *mysql, struct mxq_job **jobs_result, uint64_t group_id, struct mxq_daemon *daemon) | |
{ | |
struct mxq_job *jobs_tmp = NULL; | |
struct mx_mysql_bind param = {0}; | |
int res; | |
int idx; | |
assert(mysql); | |
assert(jobs_result); | |
assert(!(*jobs_result)); | |
assert(daemon); | |
assert(daemon->daemon_id); | |
char *query = | |
"SELECT" | |
JOB_FIELDS | |
" FROM" | |
" mxq_job" | |
" WHERE job_status = " status_str(MXQ_JOB_STATUS_ASSIGNED) | |
" AND group_id = ?" | |
" AND daemon_id = ?" | |
" LIMIT 1"; | |
mx_mysql_bind_init_param(¶m, 2); | |
idx = 0; | |
mx_mysql_bind_var(¶m, idx++, uint64, &group_id); | |
mx_mysql_bind_var(¶m, idx++, uint32, &daemon->daemon_id); | |
res = do_jobs_statement(mysql, query, ¶m, &jobs_tmp); | |
if (res >= 0) | |
*jobs_result = jobs_tmp; | |
return res; | |
} | |
int mxq_load_job_from_group_for_daemon(struct mx_mysql *mysql, struct mxq_job *job, uint64_t group_id, struct mxq_daemon *daemon, | |
unsigned long slots_per_job) | |
{ | |
int res; | |
struct mxq_job *jobs_tmp = NULL; | |
assert(mysql); | |
assert(job); | |
assert(daemon); | |
do { | |
res = mxq_load_job_from_group_assigned_to_daemon(mysql, &jobs_tmp, group_id, daemon); | |
if(res < 0) { | |
return 0; | |
} | |
if(res == 1) { | |
memcpy(job, &jobs_tmp[0], sizeof(*job)); | |
mx_free_null(jobs_tmp); | |
break; | |
} | |
res = mxq_assign_job_from_group_to_daemon(mysql, group_id, daemon, slots_per_job); | |
if (res < 0) { | |
return 0; | |
} | |
if (res == 0) { | |
mx_log_warning(" group_id=%lu :: mxq_assign_job_from_group_to_daemon(): No matching job found - maybe another server was a bit faster. ;)", group_id); | |
return 0; | |
} | |
} while (1); | |
res = mxq_set_job_status_loaded_on_server(mysql, job); | |
if (res < 0) { | |
return 0; | |
} | |
if (res == 0) { | |
mx_log_err(" group_id=%lu job_id=%lu :: mxq_set_job_status_loaded_on_server(): Job not found", group_id, job->job_id); | |
return 0; | |
} | |
job->job_status = MXQ_JOB_STATUS_LOADED; | |
return 1; | |
} | |
int mxq_load_jobs_running_on_server(struct mx_mysql *mysql, struct mxq_job **jobs_result, struct mxq_daemon *daemon) | |
{ | |
struct mxq_job *jobs_tmp = NULL; | |
struct mx_mysql_bind param = {0}; | |
int idx; | |
int res; | |
assert(daemon); | |
assert(daemon->hostname); | |
assert(daemon->daemon_name); | |
assert(*daemon->hostname); | |
assert(*daemon->daemon_name); | |
char *query = | |
"SELECT" | |
JOB_FIELDS | |
" FROM" | |
" mxq_job" | |
" WHERE job_status IN (" | |
status_str(MXQ_JOB_STATUS_LOADED) "," | |
status_str(MXQ_JOB_STATUS_RUNNING) ")" | |
" AND host_hostname = ?" | |
" AND server_id = ?"; | |
mx_mysql_bind_init_param(¶m, 2); | |
idx = 0; | |
mx_mysql_bind_var(¶m, idx++, string, &daemon->hostname); | |
mx_mysql_bind_var(¶m, idx++, string, &daemon->daemon_name); | |
res=do_jobs_statement(mysql, query, ¶m, &jobs_tmp); | |
if (res >= 0) | |
*jobs_result = jobs_tmp; | |
return res; | |
} | |
int mxq_unload_job_from_server(struct mx_mysql *mysql, uint64_t job_id) { | |
/* set a job from LOADED back to INQ. This needs to reset what | |
* mxq_assign_job_from_group_to_daemon() and mxq_set_job_status_loaded_on_server() | |
* did to the job: | |
* | |
* mxq_assign_job_from_group_to_daemon() : daemon_id, host_hostname, host_slots, server_id, job_status | |
* mxq_set_job_status_loaded_on_server() : host_id, job_status | |
* | |
* Only to be used as an error path, if we fail after loading a job during job setup | |
* before any users code was executed (with possible user-visible side effects) | |
*/ | |
struct mx_mysql_bind param = {0}; | |
int res; | |
char *query = | |
"UPDATE" | |
" mxq_job" | |
" SET" | |
" daemon_id = 0," | |
" host_hostname = ''," | |
" host_slots = 0," | |
" server_id = ''," | |
" host_id = ''," | |
" job_status = " status_str(MXQ_JOB_STATUS_INQ) | |
" WHERE" | |
" job_id = ?" | |
" AND job_status = " status_str(MXQ_JOB_STATUS_LOADED); | |
mx_mysql_bind_init_param(¶m, 1); | |
mx_mysql_bind_var(¶m, 0, uint64, &(job_id)); | |
res = mx_mysql_do_statement_noresult_retry_on_fail(mysql, query, ¶m); | |
if (res < 0) { | |
mx_log_err("mx_mysql_do_statement(): %s", mx_mysql_error()); | |
return res; | |
} | |
return res; | |
} |