From bba1452a9528161cc4c46d6b17f477b67da9377e Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 19 Oct 2015 15:56:54 +0200 Subject: [PATCH 01/34] mxqd: set MXQ_HOSTID in main process This enables external programs to read it from the process environment --- mxqd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mxqd.c b/mxqd.c index 48b5e9be..d4e53723 100644 --- a/mxqd.c +++ b/mxqd.c @@ -507,6 +507,7 @@ int server_init(struct mxq_server *server, int argc, char *argv[]) mx_proc_pid_stat_free(&pps); mx_asprintf_forever(&server->host_id, "%s-%llx-%x", server->boot_id, server->starttime, getpid()); + mx_setenv_forever("MXQ_HOSTID", server->host_id); server->slots = threads_total; res = cpuset_init(server); From 295c8df2c1bcae3f3afd60a45ec287eb6d644212 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Thu, 22 Oct 2015 21:26:51 +0200 Subject: [PATCH 02/34] mx_proc: Move process related function from mx_util to mx_proc --- .gitignore | 1 + Makefile | 13 ++++++ mx_proc.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++ mx_proc.h | 58 ++++++++++++++++++++++++++ mx_util.c | 98 ------------------------------------------- mx_util.h | 51 ----------------------- mxqd.c | 8 ++-- test_mx_util.c | 24 ++++------- 8 files changed, 196 insertions(+), 168 deletions(-) create mode 100644 mx_proc.c create mode 100644 mx_proc.h diff --git a/.gitignore b/.gitignore index d6af43fc..f466977c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ mx_getopt.o mx_flock.o mx_log.o mx_util.o +mx_proc.o mxq_group.o mxqadmin.o mxqdump.o diff --git a/Makefile b/Makefile index dad0d7d2..ca31600f 100644 --- a/Makefile +++ b/Makefile @@ -242,6 +242,10 @@ mx_log.h += mx_log.h mx_util.h += mx_util.h +### mx_proc.h ---------------------------------------------------------- + +mx_proc.h += mx_proc.h + ### mx_flock.h --------------------------------------------------------- mx_flock.h += mx_flock.h @@ -292,6 +296,12 @@ mx_util.o: $(mx_log.h) clean: CLEAN += mx_util.o +### mx_proc ------------------------------------------------------------ + +mx_proc.o: $(mx_proc.h) + +clean: CLEAN += mx_proc.o + ### mx_flock.o --------------------------------------------------------- mx_flock.o: $(mx_flock.h) @@ -373,6 +383,7 @@ clean: CLEAN += mxq_job.o mxqd.o: $(mx_getopt.h) mxqd.o: $(mx_flock.h) mxqd.o: $(mx_util.h) +mxqd.o: $(mx_proc.h) mxqd.o: $(mx_log.h) mxqd.o: $(mxqd.h) mxqd.o: $(mxq_group.h) @@ -405,6 +416,7 @@ clean: CLEAN += mxqsub.o mxqd: mx_flock.o mxqd: mx_util.o +mxqd: mx_proc.o mxqd: mx_log.o mxqd: mxq_log.o mxqd: mx_getopt.o @@ -522,6 +534,7 @@ test_mx_util.o: $(mx_util.h) clean: CLEAN += test_mx_util.o test_mx_util: mx_util.o +test_mx_util: mx_proc.o test_mx_util: mx_log.o clean: CLEAN += test_mx_util diff --git a/mx_proc.c b/mx_proc.c new file mode 100644 index 00000000..2af1a5da --- /dev/null +++ b/mx_proc.c @@ -0,0 +1,111 @@ +#include +#include +#include +#include + +#include "mx_util.h" +#include "mx_proc.h" + +static int _mx_proc_pid_stat_strscan(char *str, struct mx_proc_pid_stat *pps) +{ + size_t res = 0; + char *p; + char *s; + + pps->comm = NULL; + + s = str; + + res += mx_strscan_ll(&s, &(pps->pid)); + + p = strrchr(s, ')'); + if (!p) + return -(errno=EINVAL); + + *p = 0; + s++; + + pps->comm = mx_strdup_forever(s); + s = p + 2; + + pps->state = *s; + res += !(*(s+1) == ' '); + s += 2; + + res += mx_strscan_ll(&s, &(pps->ppid)); + res += mx_strscan_ll(&s, &(pps->pgrp)); + res += mx_strscan_ll(&s, &(pps->session)); + res += mx_strscan_ll(&s, &(pps->tty_nr)); + res += mx_strscan_ll(&s, &(pps->tpgid)); + res += mx_strscan_ull(&s, &(pps->flags)); + res += mx_strscan_ull(&s, &(pps->minflt)); + res += mx_strscan_ull(&s, &(pps->cminflt)); + res += mx_strscan_ull(&s, &(pps->majflt)); + res += mx_strscan_ull(&s, &(pps->cmajflt)); + res += mx_strscan_ull(&s, &(pps->utime)); + res += mx_strscan_ull(&s, &(pps->stime)); + res += mx_strscan_ll(&s, &(pps->cutime)); + res += mx_strscan_ll(&s, &(pps->cstime)); + res += mx_strscan_ll(&s, &(pps->priority)); + res += mx_strscan_ll(&s, &(pps->nice)); + res += mx_strscan_ll(&s, &(pps->num_threads)); + res += mx_strscan_ll(&s, &(pps->itrealvalue)); + res += mx_strscan_ull(&s, &(pps->starttime)); + res += mx_strscan_ull(&s, &(pps->vsize)); + res += mx_strscan_ll(&s, &(pps->rss)); + res += mx_strscan_ull(&s, &(pps->rsslim)); + res += mx_strscan_ull(&s, &(pps->startcode)); + res += mx_strscan_ull(&s, &(pps->endcode)); + res += mx_strscan_ull(&s, &(pps->startstack)); + res += mx_strscan_ull(&s, &(pps->kstkesp)); + res += mx_strscan_ull(&s, &(pps->kstkeip)); + res += mx_strscan_ull(&s, &(pps->signal)); + res += mx_strscan_ull(&s, &(pps->blocked)); + res += mx_strscan_ull(&s, &(pps->sigignore)); + res += mx_strscan_ull(&s, &(pps->sigcatch)); + res += mx_strscan_ull(&s, &(pps->wchan)); + res += mx_strscan_ull(&s, &(pps->nswap)); + res += mx_strscan_ull(&s, &(pps->cnswap)); + res += mx_strscan_ll(&s, &(pps->exit_signal)); + res += mx_strscan_ll(&s, &(pps->processor)); + res += mx_strscan_ull(&s, &(pps->rt_priority)); + res += mx_strscan_ull(&s, &(pps->policy)); + res += mx_strscan_ull(&s, &(pps->delayacct_blkio_ticks)); + res += mx_strscan_ull(&s, &(pps->guest_time)); + res += mx_strscan_ll(&s, &(pps->cguest_time)); + + if (res != 0) + return -(errno=EINVAL); + + return 0; +} + +int mx_proc_pid_stat(struct mx_proc_pid_stat **pps, pid_t pid) +{ + _mx_cleanup_free_ char *fname = NULL; + _mx_cleanup_free_ char *line = NULL; + int res; + + mx_asprintf_forever(&fname, "/proc/%d/stat", pid); + + if (!*pps) + *pps = mx_calloc_forever(1, sizeof(**pps)); + + res = mx_read_first_line_from_file(fname, &line); + if (res < 0) + return res; + + res = _mx_proc_pid_stat_strscan(line, *pps); + if (res < 0) + return res; + + return 0; +} + +void mx_proc_pid_stat_free_content(struct mx_proc_pid_stat *pps) +{ + if (!pps) + return; + + mx_free_null(pps->comm); +} diff --git a/mx_proc.h b/mx_proc.h new file mode 100644 index 00000000..4a0efb8e --- /dev/null +++ b/mx_proc.h @@ -0,0 +1,58 @@ +#ifndef __MX_PROC_H__ +#define __MX_PROC_H__ 1 + +#include + +struct mx_proc_pid_stat { + long long int pid; /* 1 */ + char *comm; /* 2 (comm) */ + char state; /* 3 "RSDZTW" */ + long long int ppid; /* 4 */ + long long int pgrp; /* 5 */ + long long int session; /* 6 */ + long long int tty_nr; /* 7 */ + long long int tpgid; /* 8 */ + unsigned long long int flags; /* 9 */ + unsigned long long int minflt; /* 10 */ + unsigned long long int cminflt; /* 11 */ + unsigned long long int majflt; /* 12 */ + unsigned long long int cmajflt; /* 13 */ + unsigned long long int utime; /* 14 */ + unsigned long long int stime; /* 15 */ + long long int cutime; /* 16 */ + long long int cstime; /* 17 */ + long long int priority; /* 18 */ + long long int nice; /* 19 */ + long long int num_threads; /* 20 */ + long long int itrealvalue; /* 21 */ + unsigned long long int starttime; /* 22 */ + unsigned long long int vsize; /* 23 */ + long long int rss; /* 24 */ + unsigned long long int rsslim; /* 25 */ + unsigned long long int startcode; /* 26 */ + unsigned long long int endcode; /* 27 */ + unsigned long long int startstack; /* 28 */ + unsigned long long int kstkesp; /* 29 */ + unsigned long long int kstkeip; /* 30 */ + unsigned long long int signal; /* 31 */ + unsigned long long int blocked; /* 32 */ + unsigned long long int sigignore; /* 33 */ + unsigned long long int sigcatch; /* 34 */ + unsigned long long int wchan; /* 35 */ + unsigned long long int nswap; /* 36 */ + unsigned long long int cnswap; /* 37 */ + long long int exit_signal; /* 38 */ + long long int processor; /* 39 */ + unsigned long long int rt_priority; /* 40 */ + unsigned long long int policy; /* 41 */ + unsigned long long int delayacct_blkio_ticks; /* 42 */ + unsigned long long int guest_time; /* 43 */ + long long int cguest_time; /* 44 */ +}; + +int mx_proc_pid_stat_read(struct mx_proc_pid_stat *pps, char *fmt, ...); +int mx_proc_pid_stat(struct mx_proc_pid_stat **pps, pid_t pid); + +void mx_proc_pid_stat_free_content(struct mx_proc_pid_stat *pps); + +#endif diff --git a/mx_util.c b/mx_util.c index 24088b2c..f783ed38 100644 --- a/mx_util.c +++ b/mx_util.c @@ -856,104 +856,6 @@ int mx_strscan_ll(char **str, long long int *to) return res; } -int mx_strscan_proc_pid_stat(char *str, struct proc_pid_stat *pps) -{ - size_t res = 0; - char *p; - char *s; - - pps->comm = NULL; - - s = str; - - res += mx_strscan_ll(&s, &(pps->pid)); - - p = strrchr(s, ')'); - if (!p) - return -(errno=EINVAL); - - *p = 0; - s++; - - pps->comm = mx_strdup_forever(s); - s = p + 2; - - pps->state = *s; - res += !(*(s+1) == ' '); - s += 2; - - res += mx_strscan_ll(&s, &(pps->ppid)); - res += mx_strscan_ll(&s, &(pps->pgrp)); - res += mx_strscan_ll(&s, &(pps->session)); - res += mx_strscan_ll(&s, &(pps->tty_nr)); - res += mx_strscan_ll(&s, &(pps->tpgid)); - res += mx_strscan_ull(&s, &(pps->flags)); - res += mx_strscan_ull(&s, &(pps->minflt)); - res += mx_strscan_ull(&s, &(pps->cminflt)); - res += mx_strscan_ull(&s, &(pps->majflt)); - res += mx_strscan_ull(&s, &(pps->cmajflt)); - res += mx_strscan_ull(&s, &(pps->utime)); - res += mx_strscan_ull(&s, &(pps->stime)); - res += mx_strscan_ll(&s, &(pps->cutime)); - res += mx_strscan_ll(&s, &(pps->cstime)); - res += mx_strscan_ll(&s, &(pps->priority)); - res += mx_strscan_ll(&s, &(pps->nice)); - res += mx_strscan_ll(&s, &(pps->num_threads)); - res += mx_strscan_ll(&s, &(pps->itrealvalue)); - res += mx_strscan_ull(&s, &(pps->starttime)); - res += mx_strscan_ull(&s, &(pps->vsize)); - res += mx_strscan_ll(&s, &(pps->rss)); - res += mx_strscan_ull(&s, &(pps->rsslim)); - res += mx_strscan_ull(&s, &(pps->startcode)); - res += mx_strscan_ull(&s, &(pps->endcode)); - res += mx_strscan_ull(&s, &(pps->startstack)); - res += mx_strscan_ull(&s, &(pps->kstkesp)); - res += mx_strscan_ull(&s, &(pps->kstkeip)); - res += mx_strscan_ull(&s, &(pps->signal)); - res += mx_strscan_ull(&s, &(pps->blocked)); - res += mx_strscan_ull(&s, &(pps->sigignore)); - res += mx_strscan_ull(&s, &(pps->sigcatch)); - res += mx_strscan_ull(&s, &(pps->wchan)); - res += mx_strscan_ull(&s, &(pps->nswap)); - res += mx_strscan_ull(&s, &(pps->cnswap)); - res += mx_strscan_ll(&s, &(pps->exit_signal)); - res += mx_strscan_ll(&s, &(pps->processor)); - res += mx_strscan_ull(&s, &(pps->rt_priority)); - res += mx_strscan_ull(&s, &(pps->policy)); - res += mx_strscan_ull(&s, &(pps->delayacct_blkio_ticks)); - res += mx_strscan_ull(&s, &(pps->guest_time)); - res += mx_strscan_ll(&s, &(pps->cguest_time)); - - if (res != 0) - return -(errno=EINVAL); - - return 0; -} - -int mx_proc_pid_stat(struct proc_pid_stat *pps, pid_t pid) -{ - _mx_cleanup_free_ char *fname = NULL; - _mx_cleanup_free_ char *line = NULL; - int res; - - mx_asprintf_forever(&fname, "/proc/%d/stat", pid); - - res = mx_read_first_line_from_file(fname, &line); - if (res < 0) - return res; - - res = mx_strscan_proc_pid_stat(line, pps); - if (res < 0) - return res; - - return 0; -} - -void mx_proc_pid_stat_free(struct proc_pid_stat *pps) -{ - mx_free_null(pps->comm); -} - int mx_sleep(unsigned int seconds) { if (seconds) diff --git a/mx_util.h b/mx_util.h index aeb24894..16a27d37 100644 --- a/mx_util.h +++ b/mx_util.h @@ -10,53 +10,6 @@ #include "mx_log.h" -struct proc_pid_stat { - long long int pid; /* 1 */ - char *comm; /* 2 (comm) */ - char state; /* 3 "RSDZTW" */ - long long int ppid; /* 4 */ - long long int pgrp; /* 5 */ - long long int session; /* 6 */ - long long int tty_nr; /* 7 */ - long long int tpgid; /* 8 */ - unsigned long long int flags; /* 9 */ - unsigned long long int minflt; /* 10 */ - unsigned long long int cminflt; /* 11 */ - unsigned long long int majflt; /* 12 */ - unsigned long long int cmajflt; /* 13 */ - unsigned long long int utime; /* 14 */ - unsigned long long int stime; /* 15 */ - long long int cutime; /* 16 */ - long long int cstime; /* 17 */ - long long int priority; /* 18 */ - long long int nice; /* 19 */ - long long int num_threads; /* 20 */ - long long int itrealvalue; /* 21 */ - unsigned long long int starttime; /* 22 */ - unsigned long long int vsize; /* 23 */ - long long int rss; /* 24 */ - unsigned long long int rsslim; /* 25 */ - unsigned long long int startcode; /* 26 */ - unsigned long long int endcode; /* 27 */ - unsigned long long int startstack; /* 28 */ - unsigned long long int kstkesp; /* 29 */ - unsigned long long int kstkeip; /* 30 */ - unsigned long long int signal; /* 31 */ - unsigned long long int blocked; /* 32 */ - unsigned long long int sigignore; /* 33 */ - unsigned long long int sigcatch; /* 34 */ - unsigned long long int wchan; /* 35 */ - unsigned long long int nswap; /* 36 */ - unsigned long long int cnswap; /* 37 */ - long long int exit_signal; /* 38 */ - long long int processor; /* 39 */ - unsigned long long int rt_priority; /* 40 */ - unsigned long long int policy; /* 41 */ - unsigned long long int delayacct_blkio_ticks; /* 42 */ - unsigned long long int guest_time; /* 43 */ - long long int cguest_time; /* 44 */ -}; - #ifdef MX_NDEBUG # include # define mx_assert_return_minus_errno(test, eno) \ @@ -168,10 +121,6 @@ int mx_read_first_line_from_file(char *fname, char **line); int mx_strscan_ull(char **str, unsigned long long int *to); int mx_strscan_ll(char **str, long long int *to); -int mx_strscan_proc_pid_stat(char *str, struct proc_pid_stat *pps); - -int mx_proc_pid_stat(struct proc_pid_stat *pps, pid_t pid); -void mx_proc_pid_stat_free(struct proc_pid_stat *pps); int mx_sleep(unsigned int seconds); int mx_sleep_nofail(unsigned int seconds); diff --git a/mxqd.c b/mxqd.c index d4e53723..77706c73 100644 --- a/mxqd.c +++ b/mxqd.c @@ -34,6 +34,7 @@ #include "mxq_group.h" #include "mxq_job.h" #include "mx_mysql.h" +#include "mx_proc.h" #include "mxqd.h" #include "mxq.h" @@ -281,7 +282,8 @@ int server_init(struct mxq_server *server, int argc, char *argv[]) unsigned long memory_total = 2048; unsigned long memory_max = 0; int i; - struct proc_pid_stat pps = {0}; + + _mx_cleanup_free_ struct mx_proc_pid_stat *pps = NULL; struct mx_getopt_ctl optctl; struct mx_option opts[] = { @@ -503,8 +505,8 @@ int server_init(struct mxq_server *server, int argc, char *argv[]) res = mx_proc_pid_stat(&pps, getpid()); assert(res == 0); - server->starttime = pps.starttime; - mx_proc_pid_stat_free(&pps); + server->starttime = pps->starttime; + mx_proc_pid_stat_free_content(pps); mx_asprintf_forever(&server->host_id, "%s-%llx-%x", server->boot_id, server->starttime, getpid()); mx_setenv_forever("MXQ_HOSTID", server->host_id); diff --git a/test_mx_util.c b/test_mx_util.c index b290490a..817fbef5 100644 --- a/test_mx_util.c +++ b/test_mx_util.c @@ -8,6 +8,7 @@ #include #include "mx_util.h" +#include "mx_proc.h" static void test_mx_strskipwhitespaces(void) { @@ -305,8 +306,7 @@ static void test_mx_strscan(void) unsigned long long int ull; long long int ll; _mx_cleanup_free_ char *line = NULL; - struct proc_pid_stat pps = {0}; - struct proc_pid_stat pps2 = {0}; + _mx_cleanup_free_ struct mx_proc_pid_stat *pps = NULL; assert(s = strdup("123 456 -789 246 abc")); str = s; @@ -340,20 +340,12 @@ static void test_mx_strscan(void) assert(mx_streq(str, "")); assert(mx_streq(s, "123")); - assert(mx_read_first_line_from_file("/proc/self/stat", &line) > 0); - assert(mx_strscan_proc_pid_stat(line, &pps) == 0); - assert(pps.pid == getpid()); - assert(pps.ppid == getppid()); - assert(pps.state == 'R'); - assert(mx_streq(pps.comm, program_invocation_short_name) || mx_streq(pps.comm, "memcheck-amd64-")); - mx_proc_pid_stat_free(&pps); - - assert(mx_proc_pid_stat(&pps2, getpid()) == 0); - assert(pps2.pid == getpid()); - assert(pps2.ppid == getppid()); - assert(pps2.state == 'R'); - assert(mx_streq(pps2.comm, program_invocation_short_name) || mx_streq(pps2.comm, "memcheck-amd64-")); - mx_proc_pid_stat_free(&pps2); + assert(mx_proc_pid_stat(&pps, getpid()) == 0); + assert(pps->pid == getpid()); + assert(pps->ppid == getppid()); + assert(pps->state == 'R'); + assert(mx_streq(pps->comm, program_invocation_short_name) || mx_streq(pps->comm, "memcheck-amd64-")); + mx_proc_pid_stat_free(pps); } static void test_mx_strvec() { From dbc742dda6c11926df09ede74ea015465e2bb574 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Sat, 24 Oct 2015 14:09:25 +0200 Subject: [PATCH 03/34] Makefile: Add new target devel and remove nonroot using devel will: * define MXQ_DEVELOPMENT * change MXQ_MYSQL_DEFAULT_GROUP to mxqdevel for servers and clients * add warning to --help and to the mxqd logfile * change the default for --no-log to true in mxqd --- Makefile | 15 ++++++++++----- mxq.h | 21 +++++++++++++++++++-- mxqd.c | 23 +++++++++++++++++------ 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index 716bc3f3..c0f38500 100644 --- a/Makefile +++ b/Makefile @@ -60,13 +60,17 @@ CGIDIR = ${LIBEXECDIR}/mxq/cgi ######################################################################## MXQ_MYSQL_DEFAULT_FILE = ${SYSCONFDIR}/mxq/mysql.cnf -MXQ_MYSQL_DEFAULT_GROUP = mxqclient +MXQ_MYSQL_DEFAULT_GROUP_CLIENT = mxqclient +MXQ_MYSQL_DEFAULT_GROUP_SERVER = mxqd +MXQ_MYSQL_DEFAULT_GROUP_DEVELOPMENT = mxqdevel MXQ_INITIAL_PATH = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin MXQ_INITIAL_TMPDIR = /tmp CFLAGS_MXQ_MYSQL_DEFAULT_FILE = -DMXQ_MYSQL_DEFAULT_FILE=\"$(MXQ_MYSQL_DEFAULT_FILE)\" -CFLAGS_MXQ_MYSQL_DEFAULT_GROUP = -DMXQ_MYSQL_DEFAULT_GROUP=\"$(MXQ_MYSQL_DEFAULT_GROUP)\" +CFLAGS_MXQ_MYSQL_DEFAULT_GROUP = -DMXQ_MYSQL_DEFAULT_GROUP_CLIENT=\"$(MXQ_MYSQL_DEFAULT_GROUP_CLIENT)\" +CFLAGS_MXQ_MYSQL_DEFAULT_GROUP += -DMXQ_MYSQL_DEFAULT_GROUP_SERVER=\"$(MXQ_MYSQL_DEFAULT_GROUP_SERVER)\" +CFLAGS_MXQ_MYSQL_DEFAULT_GROUP += -DMXQ_MYSQL_DEFAULT_GROUP_DEVELOPMENT=\"$(MXQ_MYSQL_DEFAULT_GROUP_DEVELOPMENT)\" CFLAGS_MXQ_INITIAL_PATH = -DMXQ_INITIAL_PATH=\"$(MXQ_INITIAL_PATH)\" CFLAGS_MXQ_INITIAL_TMPDIR = -DMXQ_INITIAL_TMPDIR=\"$(MXQ_INITIAL_TMPDIR)\" @@ -184,9 +188,10 @@ manpages/%: manpages/%.xml all: build -.PHONY: nonroot -nonroot: CFLAGS += -DRUNASNORMALUSER -nonroot: all +.PHONY: devel +devel: CFLAGS += -DRUNASNORMALUSER +devel: CFLAGS += -DMXQ_DEVELOPMENT +devel: all ######################################################################## diff --git a/mxq.h b/mxq.h index 22c5842c..556db6f7 100644 --- a/mxq.h +++ b/mxq.h @@ -27,8 +27,22 @@ # define MXQ_MYSQL_DEFAULT_FILE_STR MXQ_MYSQL_DEFAULT_FILE #endif -#ifndef MXQ_MYSQL_DEFAULT_GROUP -# define MXQ_MYSQL_DEFAULT_GROUP program_invocation_short_name +#ifdef MXQ_DEVELOPMENT +# undef MXQ_MYSQL_DEFAULT_GROUP +# define MXQ_MYSQL_DEFAULT_GROUP MXQ_MYSQL_DEFAULT_GROUP_DEVELOPMENT +#else +# ifdef MXQ_TYPE_SERVER +# ifdef MXQ_MYSQL_DEFAULT_GROUP_SERVER +# define MXQ_MYSQL_DEFAULT_GROUP MXQ_MYSQL_DEFAULT_GROUP_SERVER +# endif +# else +# ifdef MXQ_MYSQL_DEFAULT_GROUP_CLIENT +# define MXQ_MYSQL_DEFAULT_GROUP MXQ_MYSQL_DEFAULT_GROUP_CLIENT +# endif +# endif +# ifndef MXQ_MYSQL_DEFAULT_GROUP +# define MXQ_MYSQL_DEFAULT_GROUP program_invocation_short_name +# endif #endif #define MXQ_MYSQL_DEFAULT_GROUP_STR MXQ_MYSQL_DEFAULT_GROUP @@ -36,6 +50,9 @@ static void mxq_print_generic_version(void) { printf( "%s - " MXQ_VERSIONFULL "\n" +#ifdef MXQ_DEVELOPMENT + "DEVELOPMENT VERSION: Do not use in production environments.\n" +#endif " by Marius Tolzmann " MXQ_VERSIONDATE "\n" " Max Planck Institute for Molecular Genetics - Berlin Dahlem\n", program_invocation_short_name diff --git a/mxqd.c b/mxqd.c index 047b6ed4..55f94864 100644 --- a/mxqd.c +++ b/mxqd.c @@ -1,6 +1,8 @@ #define _GNU_SOURCE +#define MXQ_TYPE_SERVER + #include #include #include @@ -37,9 +39,6 @@ #include "mxqd.h" #include "mxq.h" -#define MYSQL_DEFAULT_FILE MXQ_MYSQL_DEFAULT_FILE -#define MYSQL_DEFAULT_GROUP "mxqd" - #ifndef MXQ_INITIAL_PATH # define MXQ_INITIAL_PATH "/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin" #endif @@ -71,7 +70,11 @@ static void print_usage(void) "\n" " --pid-file default: create no pid file\n" " --daemonize default: run in foreground\n" +#ifdef MXQ_DEVELOPMENT + " --log default (in development): write no logfile\n" +#else " --no-log default: write a logfile\n" +#endif " --debug default: info log level\n" " --recover-only (recover from crash and exit)\n" "\n" @@ -289,6 +292,7 @@ int server_init(struct mxq_server *server, int argc, char *argv[]) MX_OPTION_NO_ARG("version", 'V'), MX_OPTION_NO_ARG("daemonize", 1), MX_OPTION_NO_ARG("no-log", 3), + MX_OPTION_NO_ARG("log", 4), MX_OPTION_NO_ARG("debug", 5), MX_OPTION_NO_ARG("recover-only", 9), MX_OPTION_REQUIRED_ARG("pid-file", 2), @@ -312,11 +316,11 @@ int server_init(struct mxq_server *server, int argc, char *argv[]) arg_mysql_default_group = getenv("MXQ_MYSQL_DEFAULT_GROUP"); if (!arg_mysql_default_group) - arg_mysql_default_group = MYSQL_DEFAULT_GROUP; + arg_mysql_default_group = MXQ_MYSQL_DEFAULT_GROUP; arg_mysql_default_file = getenv("MXQ_MYSQL_DEFAULT_FILE"); if (!arg_mysql_default_file) - arg_mysql_default_file = MYSQL_DEFAULT_FILE; + arg_mysql_default_file = MXQ_MYSQL_DEFAULT_FILE; mx_getopt_init(&optctl, argc-1, &argv[1], opts); @@ -340,6 +344,10 @@ int server_init(struct mxq_server *server, int argc, char *argv[]) arg_nolog = 1; break; + case 4: + arg_nolog = 0; + break; + case 5: mx_log_level_set(MX_LOG_DEBUG); break; @@ -486,7 +494,7 @@ int server_init(struct mxq_server *server, int argc, char *argv[]) } if (getuid()) { -#ifdef RUNASNORMALUSER +#if defined(MXQ_DEVELOPMENT) || defined(RUNASNORMALUSER) mx_log_notice("Running mxqd as non-root user."); #else mx_log_err("Running mxqd as non-root user is not supported at the moment."); @@ -1815,6 +1823,9 @@ int main(int argc, char *argv[]) mx_log_info("mxqd - " MXQ_VERSIONFULL); mx_log_info(" by Marius Tolzmann " MXQ_VERSIONDATE); mx_log_info(" Max Planck Institute for Molecular Genetics - Berlin Dahlem"); +#ifdef MXQ_DEVELOPMENT + mx_log_warning("DEVELOPMENT VERSION: Do not use in production environments.\n"); +#endif mx_log_info("hostname=%s server_id=%s :: MXQ server started.", server.hostname, server.server_id); mx_log_info(" host_id=%s", server.host_id); mx_log_info("slots=%lu memory_total=%lu memory_avg_per_slot=%.0Lf memory_max_per_slot=%ld :: server initialized.", From af5dde30030ea45ea6802209b4147aed59ca620c Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Sat, 24 Oct 2015 02:00:56 +0200 Subject: [PATCH 04/34] mxqd: Introduce new macro RUNNING_AS_ROOT --- mxqd.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/mxqd.c b/mxqd.c index 4de4b44b..261cb1d0 100644 --- a/mxqd.c +++ b/mxqd.c @@ -47,6 +47,8 @@ # define MXQ_INITIAL_TMPDIR "/tmp" #endif +#define RUNNING_AS_ROOT (getuid() == 0) + volatile sig_atomic_t global_sigint_cnt=0; volatile sig_atomic_t global_sigterm_cnt=0; @@ -493,7 +495,7 @@ int server_init(struct mxq_server *server, int argc, char *argv[]) } } - if (getuid()) { + if (!RUNNING_AS_ROOT) { #if defined(MXQ_DEVELOPMENT) || defined(RUNASNORMALUSER) mx_log_notice("Running mxqd as non-root user."); #else @@ -526,7 +528,7 @@ int server_init(struct mxq_server *server, int argc, char *argv[]) server->memory_max_per_slot = arg_memory_max; /* if run as non-root use full memory by default for every job */ - if (!arg_memory_max && getuid() != 0) + if (!arg_memory_max && !RUNNING_AS_ROOT) server->memory_max_per_slot = arg_memory_total; server->memory_avg_per_slot = (long double)server->memory_total / (long double)server->slots; @@ -976,7 +978,7 @@ static int init_child_process(struct mxq_group_list *group, struct mxq_job *j) g->user_name, g->user_uid, g->group_id, j->job_id); } - if(getuid()==0) { + if(RUNNING_AS_ROOT) { res = initgroups(passwd->pw_name, g->user_gid); if (res == -1) { @@ -1738,7 +1740,7 @@ int load_groups(struct mxq_server *server) { int total; int i; - if (getuid() == 0) + if (RUNNING_AS_ROOT) group_cnt = mxq_load_running_groups(server->mysql, &mxqgroups); else group_cnt = mxq_load_running_groups_for_user(server->mysql, &mxqgroups, getuid()); From 62ddc9b17a695bfb3ce921f2bd40197a35444d47 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Sat, 24 Oct 2015 15:06:57 +0200 Subject: [PATCH 05/34] MXQ: update credits --- Makefile | 2 +- mxq.h | 5 +++-- mxqd.c | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index c0f38500..eb923d81 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ MXQ_VERSION_MAJOR = 0 MXQ_VERSION_MINOR = 17 MXQ_VERSION_PATCH = 0 MXQ_VERSION_EXTRA = "beta" -MXQ_VERSIONDATE = 2013-2015 +MXQ_VERSIONDATE = 2015 MXQ_VERSION_GIT := $(shell git describe --long 2>/dev/null) diff --git a/mxq.h b/mxq.h index 556db6f7..54b073f9 100644 --- a/mxq.h +++ b/mxq.h @@ -17,7 +17,7 @@ #endif #ifndef MXQ_VERSIONDATE -# define MXQ_VERSIONDATE "2015" +# define MXQ_VERSIONDATE "today" #endif #ifndef MXQ_MYSQL_DEFAULT_FILE @@ -53,7 +53,8 @@ static void mxq_print_generic_version(void) #ifdef MXQ_DEVELOPMENT "DEVELOPMENT VERSION: Do not use in production environments.\n" #endif - " by Marius Tolzmann " MXQ_VERSIONDATE "\n" + " by Marius Tolzmann 2013-" MXQ_VERSIONDATE "\n" + " and Donald Buczek 2015-" MXQ_VERSIONDATE "\n" " Max Planck Institute for Molecular Genetics - Berlin Dahlem\n", program_invocation_short_name ); diff --git a/mxqd.c b/mxqd.c index 261cb1d0..cc559967 100644 --- a/mxqd.c +++ b/mxqd.c @@ -1830,7 +1830,8 @@ int main(int argc, char *argv[]) } mx_log_info("mxqd - " MXQ_VERSIONFULL); - mx_log_info(" by Marius Tolzmann " MXQ_VERSIONDATE); + mx_log_info(" by Marius Tolzmann 2013-" MXQ_VERSIONDATE); + mx_log_info(" and Donald Buczek 2015-" MXQ_VERSIONDATE); mx_log_info(" Max Planck Institute for Molecular Genetics - Berlin Dahlem"); #ifdef MXQ_DEVELOPMENT mx_log_warning("DEVELOPMENT VERSION: Do not use in production environments.\n"); From bd9deb9c62ca62f89c43e6bd2c9cdb66d9bfdca5 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Sat, 24 Oct 2015 15:32:40 +0200 Subject: [PATCH 06/34] README: Add development instructions --- README.md | 49 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index fb37fe79..6dfb2602 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ -# mxq -MXQ - mariux64 job scheduling system +# MXQ - mariux64 job scheduling system +- by Marius Tolzmann 2013-2015 +- and Donald Buczek 2015-2015 ## Sources ### Main git repository @@ -13,11 +14,49 @@ https://github.com/mariux/mxq ## Installation ### Install using `GNU make` ``` -make -make install [DESTDIR=...] +make +make install +``` +``` +make PREFIX=... +make PREFIX=... [DESTDIR=...] install ``` ### Install using `bee` ``` -bee init $(bee download git://github.molgen.mpg.de/mariux64/mxq.git) -e +bee init $(bee download git://github.molgen.mpg.de/mariux64/mxq.git) --execute bee update mxq ``` +``` +bee init $(bee download git://github.molgen.mpg.de/mariux64/mxq.git) --prefix=... --execute +bee update mxq +``` + +## Initial setup +Definitions of the tables and triggers for the MySQL database can be found in +[mysql/create_tables.sql](https://github.molgen.mpg.de/mariux64/mxq/blob/master/mysql/create_tables.sql) +Be sure to create those once and check the same +[directory for alter_tables*.sql`](https://github.molgen.mpg.de/mariux64/mxq/blob/master/mysql/) +files when upgrading. + + +## Development builds +The `devel` target in the Makefile will enable all devolopment features +by defining `MXQ_DEVELOPMENT` when compiling C sources. + +``` +make clean +make devel PREFIX=/path/to/test +make install PREFIX=/path/to/test +``` + +### Differences to production builds +Some new features and improvements are enabled in development builds. +Those features may not be tested for every situation yet and may result +in database corruption and/or failing jobs. + +#### changed `mxqd` default options +In devolopment builds `--no-log` is default (enable loggin with `--log`) + +#### Development database access +Devolopment builds default to use `[mxqdevel]` groups from mysql config files +for servers and clients (instead of the default `[mxqclient]` and `[mxqd]` groups) From 35236583e063ccbe552bcef27e20d81e8d474b98 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Sat, 24 Oct 2015 17:18:36 +0200 Subject: [PATCH 07/34] Makefile: remove definition of RUNASNORMALUSER in devel mode --- Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile b/Makefile index c0f38500..81b0c8b7 100644 --- a/Makefile +++ b/Makefile @@ -189,7 +189,6 @@ manpages/%: manpages/%.xml all: build .PHONY: devel -devel: CFLAGS += -DRUNASNORMALUSER devel: CFLAGS += -DMXQ_DEVELOPMENT devel: all From 425226ebf58a91ca8411b5162aa984157ec24519 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Sat, 24 Oct 2015 18:34:03 +0200 Subject: [PATCH 08/34] mxqd: Change default for --no-log in development build fixes dbc742dda6c11926df09ede74ea015465e2bb574 --- mxqd.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mxqd.c b/mxqd.c index 261cb1d0..35994390 100644 --- a/mxqd.c +++ b/mxqd.c @@ -313,6 +313,10 @@ int server_init(struct mxq_server *server, int argc, char *argv[]) arg_server_id = "main"; arg_hostname = mx_hostname(); +#ifdef MXQ_DEVELOPMENT + arg_nolog = 1; +#endif + arg_initial_path = MXQ_INITIAL_PATH; arg_initial_tmpdir = MXQ_INITIAL_TMPDIR; @@ -1833,7 +1837,7 @@ int main(int argc, char *argv[]) mx_log_info(" by Marius Tolzmann " MXQ_VERSIONDATE); mx_log_info(" Max Planck Institute for Molecular Genetics - Berlin Dahlem"); #ifdef MXQ_DEVELOPMENT - mx_log_warning("DEVELOPMENT VERSION: Do not use in production environments.\n"); + mx_log_warning("DEVELOPMENT VERSION: Do not use in production environments."); #endif mx_log_info("hostname=%s server_id=%s :: MXQ server started.", server.hostname, server.server_id); mx_log_info(" host_id=%s", server.host_id); From 4e2b1cdf1b0faf03e77f2351614868d008ebbabb Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Sat, 24 Oct 2015 19:43:26 +0200 Subject: [PATCH 09/34] mxqd: limit killall_over_time to run every minute if jobs are running --- mxqd.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mxqd.c b/mxqd.c index 35994390..6dff2f2a 100644 --- a/mxqd.c +++ b/mxqd.c @@ -1527,8 +1527,11 @@ int killall_over_time(struct mxq_server *server) assert(server); - /* limit killing to every >= 5 minutes */ - mx_within_rate_limit_or_return(5*60, 1); + if (!server->jobs_running) + return 0; + + /* limit killing to every >= 60 seconds */ + mx_within_rate_limit_or_return(60, 1); mx_log_info("killall_over_time: Sending signals to all jobs running longer than requested."); From cd27987b5d4153ad75586cc3ed67cf879e53d046 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Thu, 22 Oct 2015 21:28:45 +0200 Subject: [PATCH 10/34] mx_proc: Add process tree related functions --- mx_proc.c | 350 +++++++++++++++++++++++++++++++++++++++++++++++++++++- mx_proc.h | 31 +++++ 2 files changed, 377 insertions(+), 4 deletions(-) diff --git a/mx_proc.c b/mx_proc.c index 2af1a5da..611cda8b 100644 --- a/mx_proc.c +++ b/mx_proc.c @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include "mx_util.h" #include "mx_proc.h" @@ -81,21 +83,57 @@ static int _mx_proc_pid_stat_strscan(char *str, struct mx_proc_pid_stat *pps) } int mx_proc_pid_stat(struct mx_proc_pid_stat **pps, pid_t pid) +{ + struct mx_proc_pid_stat *pstat; + int res; + + pstat = *pps; + if (!pstat) + pstat = mx_calloc_forever(1, sizeof(*pstat)); + + res = mx_proc_pid_stat_read(pstat, "/proc/%d/stat", pid); + if (res < 0) + return res; + + *pps = pstat; + return 0; +} + +int mx_proc_pid_task_tid_stat(struct mx_proc_pid_stat **pps, pid_t pid, pid_t tid) +{ + struct mx_proc_pid_stat *pstat; + int res; + + pstat = *pps; + if (!pstat) + pstat = mx_calloc_forever(1, sizeof(*pstat)); + + res = mx_proc_pid_stat_read(pstat, "/proc/%d/task/%d/stat", pid, tid); + if (res < 0) + return res; + + *pps = pstat; + return 0; +} + +int mx_proc_pid_stat_read(struct mx_proc_pid_stat *pps, char *fmt, ...) { _mx_cleanup_free_ char *fname = NULL; _mx_cleanup_free_ char *line = NULL; + va_list ap; int res; - mx_asprintf_forever(&fname, "/proc/%d/stat", pid); + assert(pps); - if (!*pps) - *pps = mx_calloc_forever(1, sizeof(**pps)); + va_start(ap, fmt); + mx_vasprintf_forever(&fname, fmt, ap); + va_end(ap); res = mx_read_first_line_from_file(fname, &line); if (res < 0) return res; - res = _mx_proc_pid_stat_strscan(line, *pps); + res = _mx_proc_pid_stat_strscan(line, pps); if (res < 0) return res; @@ -109,3 +147,307 @@ void mx_proc_pid_stat_free_content(struct mx_proc_pid_stat *pps) mx_free_null(pps->comm); } + +static void mx_proc_tree_update_parent_pinfo(struct mx_proc_tree_node *this, struct mx_proc_info *pinfo) +{ + if (!this) + return; + + this->pinfo.sum_rss += pinfo->sum_rss; + + mx_proc_tree_update_parent_pinfo(this->parent, pinfo); +} + +static void mx_proc_tree_add_to_list_sorted(struct mx_proc_tree_node **ptn_ptr, struct mx_proc_tree_node *new) +{ + struct mx_proc_tree_node *current; + + assert(new); + assert(new->pinfo.pstat); + assert(!new->next); + assert(new->pinfo.pstat->pid > 0); + + current = *ptn_ptr; + + /* update stats */ + if (new->parent) { + new->parent->nchilds++; + mx_proc_tree_update_parent_pinfo(new->parent, &(new->pinfo)); + } + + /* empty list? -> start new list */ + if (!current) { + *ptn_ptr = new; + return; + } + + /* new is first entry */ + if (new->pinfo.pstat->pid < current->pinfo.pstat->pid) { + new->next = current; + *ptn_ptr = new; + return; + } + + /* find position */ + while (1) { + assert(new->pinfo.pstat->pid > current->pinfo.pstat->pid); + + /* new is last entry */ + if (!current->next) { + current->next = new; + break; + } + + assert(current->next->pinfo.pstat->pid > current->pinfo.pstat->pid); + + /* add new between current and current->next */ + if (new->pinfo.pstat->pid < current->next->pinfo.pstat->pid) { + new->next = current->next; + current->next = new; + break; + } + + current = current->next; + } + + return; +} + +static struct mx_proc_tree_node *mx_proc_tree_find_by_pid(struct mx_proc_tree_node *ptn, long long int pid) +{ + assert(ptn); + assert(pid >= 0); + + struct mx_proc_tree_node *current; + struct mx_proc_tree_node *node; + + if (pid == 0) + return NULL; + + current = ptn; + + for (current = ptn; current; current=current->next) { + if (current->pinfo.pstat->pid == pid) + return current; + + if (!current->childs) + continue; + + node = mx_proc_tree_find_by_pid(current->childs, pid); + if (node) + return node; + } + + return NULL; +} + +#define ppid_or_pgrp(x) (((x)->ppid != 1 || (x)->pid == (x)->pgrp) ? (x)->ppid : (x)->pgrp) + +static struct mx_proc_tree_node *mx_proc_tree_add(struct mx_proc_tree *pt, struct mx_proc_pid_stat *pps) +{ + assert(pps); + assert(pt); + struct mx_proc_tree_node *new; + struct mx_proc_tree_node *current; + struct mx_proc_tree_node *next; + struct mx_proc_tree_node *parent; + + new = mx_calloc_forever(1, sizeof(*new)); + + pt->nentries++; + + new->pinfo.pstat = pps; + new->pinfo.sum_rss = pps->rss; + + if (!(pt->root)) { + pt->root = new; + return new; + } + + assert(pt->root); + + /* new is second to last roots parent? -> collect */ + current = pt->root; + while (current->next) { + if (current->next->pinfo.pstat->ppid != new->pinfo.pstat->pid) { + current = current->next; + continue; + } + assert(current->next->pinfo.pstat->ppid == new->pinfo.pstat->pid); + + /* disconnect next */ + next = current->next; + current->next = current->next->next; + next->next = NULL; + + /* add as child of new */ + next->parent = new; + mx_proc_tree_add_to_list_sorted(&new->childs, next); + } + + /* new is first roots parent? -> new is new root */ + if (pt->root->pinfo.pstat->ppid == new->pinfo.pstat->pid) { + assert(!new->next); + + current = pt->root; + pt->root = pt->root->next; + + current->next = NULL; + current->parent = new; + + mx_proc_tree_add_to_list_sorted(&new->childs, current); + + if (!(pt->root)) { + pt->root = new; + return new; + } + } + + + parent = mx_proc_tree_find_by_pid(pt->root, new->pinfo.pstat->ppid); + if (parent) { + new->parent = parent; + mx_proc_tree_add_to_list_sorted(&parent->childs, new); + } else { + mx_proc_tree_add_to_list_sorted(&pt->root, new); + } + + return new; +} + +static void mx_proc_tree_reorder_roots(struct mx_proc_tree *pt) +{ + struct mx_proc_tree_node *current; + struct mx_proc_tree_node *pid1; + struct mx_proc_tree_node *last = NULL; + struct mx_proc_tree_node *next = NULL; + + for (current = pt->root; current; current = current->next) { + if (current->pinfo.pstat->pid == 1) { + pid1 = current; + break; + } + } + + if (!pid1) + return; + + for (current = pt->root; current; current = next) { + next = current->next; + + if (current->pinfo.pstat->ppid != 1) { + last = current; + continue; + } + + if (!last) { + if (!current->next) + return; + pt->root = current->next; + } else { + last->next = current->next; + } + current->next = NULL; + current->parent = pid1; + mx_proc_tree_add_to_list_sorted(&pid1->childs, current); + } +} + +static int _mx_filter_numbers(const struct dirent *d) +{ + if (!isdigit(d->d_name[0])) + return 0; + + return 1; +} + +int mx_proc_tree(struct mx_proc_tree **newtree) +{ + struct mx_proc_tree *pt; + struct dirent **namelist = NULL; + struct mx_proc_pid_stat *pps; + int n; + int i; + int res; + unsigned long long int pid; + + assert(*newtree == NULL); + + pt = mx_calloc_forever(1, sizeof(*pt)); + + n = scandir("/proc", &namelist, _mx_filter_numbers, NULL); + if (n < 0) + return -errno; + + if (n == 0) + return -(errno=ENOENT); + + for (i=0; i < n; i++) { + res = mx_strtoull(namelist[i]->d_name, &pid); + free(namelist[i]); + if (res < 0) + continue; + + pps = NULL; + res = mx_proc_pid_stat(&pps, pid); + if (res < 0) + continue; + + mx_proc_tree_add(pt, pps); + } + free(namelist); + + mx_proc_tree_reorder_roots(pt); + + *newtree = pt; + return 0; +} + +static void _mx_proc_tree_node_free_recursive(struct mx_proc_tree_node *ptn) +{ + assert(ptn); + + struct mx_proc_tree_node *current; + struct mx_proc_tree_node *next; + + for (current = ptn; current; current=next) { + + if (current->childs) + _mx_proc_tree_node_free_recursive(current->childs); + + next = current->next; + + mx_proc_pid_stat_free_content(current->pinfo.pstat); + mx_free_null(current->pinfo.pstat); + mx_free_null(current); + } + + return; +} + +int mx_proc_tree_free(struct mx_proc_tree **tree) +{ + struct mx_proc_tree *pt; + + pt = *tree; + + _mx_proc_tree_node_free_recursive(pt->root); + + mx_free_null(*tree); + + return 0; +} + +struct mx_proc_info *mx_proc_tree_proc_info(struct mx_proc_tree *tree, pid_t pid) +{ + struct mx_proc_tree_node *ptn; + + assert(tree); + + ptn = mx_proc_tree_find_by_pid(tree->root, pid); + + if (!ptn) + return NULL; + + return &(ptn->pinfo); +} diff --git a/mx_proc.h b/mx_proc.h index 4a0efb8e..9f16806e 100644 --- a/mx_proc.h +++ b/mx_proc.h @@ -3,6 +3,29 @@ #include +struct mx_proc_info { + struct mx_proc_pid_stat *pstat; + + unsigned long long int sum_rss; + + char **environment; +}; + +struct mx_proc_tree { + struct mx_proc_tree_node *root; + int nentries; +}; + +struct mx_proc_tree_node { + struct mx_proc_tree_node *parent; + struct mx_proc_tree_node *next; + + struct mx_proc_info pinfo; + + unsigned long long int nchilds; + struct mx_proc_tree_node *childs; +}; + struct mx_proc_pid_stat { long long int pid; /* 1 */ char *comm; /* 2 (comm) */ @@ -51,8 +74,16 @@ struct mx_proc_pid_stat { }; int mx_proc_pid_stat_read(struct mx_proc_pid_stat *pps, char *fmt, ...); + int mx_proc_pid_stat(struct mx_proc_pid_stat **pps, pid_t pid); +int mx_proc_pid_task_tid_stat(struct mx_proc_pid_stat **pps, pid_t pid, pid_t tid); void mx_proc_pid_stat_free_content(struct mx_proc_pid_stat *pps); +int mx_proc_tree(struct mx_proc_tree **newtree); + +int mx_proc_tree_free(struct mx_proc_tree **tree); + +struct mx_proc_info *mx_proc_tree_proc_info(struct mx_proc_tree *tree, pid_t pid); + #endif From 0a6148d3af69c52c5cba3e5e8fc33cd24baef955 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Thu, 22 Oct 2015 16:01:47 +0200 Subject: [PATCH 11/34] mxqps: Add new tool to list mxqd processes --- .gitignore | 2 ++ Makefile | 15 +++++++++ mxqps.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+) create mode 100644 mxqps.c diff --git a/.gitignore b/.gitignore index f466977c..4509600b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ mx_flock.o mx_log.o mx_util.o mx_proc.o +mxqps.o mxq_group.o mxqadmin.o mxqdump.o @@ -22,6 +23,7 @@ mxqadmin mxqdump mxqkill mxqd +mxqps test_mx_util test_mx_log test_mx_mysql diff --git a/Makefile b/Makefile index ca31600f..a1a38766 100644 --- a/Makefile +++ b/Makefile @@ -495,6 +495,21 @@ clean: CLEAN += mxqkill install:: mxqkill $(call quiet-installforuser,$(SUID_MODE),$(UID_CLIENT),$(GID_CLIENT),mxqkill,${DESTDIR}${BINDIR}/mxqkill) +### mxqps ------------------------------------------------------------- + +mxqps.o: $(mx_proc.h) +mxqps.o: $(mx_util.h) + +clean: CLEAN += mxqps.o + +mxqps: mx_log.o +mxqps: mx_util.o +mxqps: mx_proc.o + +build: mxqps + +clean: CLEAN += mxqps + ######################################################################## fix: FIX += mxqdctl-hostconfig.sh diff --git a/mxqps.c b/mxqps.c new file mode 100644 index 00000000..5088edc0 --- /dev/null +++ b/mxqps.c @@ -0,0 +1,94 @@ + +#include +#include +#include +#include +#include +#include + +#include "mx_util.h" +#include "mx_log.h" +#include "mx_proc.h" + + +int filter(const struct dirent *d) +{ + if (!isdigit(d->d_name[0])) + return 0; + + return 1; +} + +#define MX_PROC_TREE_NODE_IS_KERNEL_THREAD(x) ((x)->pinfo.pstat->ppid == 0 && (x)->pinfo.sum_rss == 0) + +int mx_proc_tree_node_print_debug(struct mx_proc_tree_node *ptn, int lvl) +{ + assert(ptn); + + struct mx_proc_tree_node *current; + + current = ptn; + + long pagesize; + + pagesize = sysconf(_SC_PAGESIZE); + assert(pagesize); + + for (current = ptn; current; current=current->next) { + if (MX_PROC_TREE_NODE_IS_KERNEL_THREAD(current)) + continue; + + printf("%7lld %7lld %7lld %7lld %15lld %15lld %7lld", + current->pinfo.pstat->pid, + current->pinfo.pstat->ppid, + current->pinfo.pstat->pgrp, + current->pinfo.pstat->session, + current->pinfo.pstat->rss*pagesize/1024, + current->pinfo.sum_rss*pagesize/1024, + current->pinfo.pstat->num_threads); + + if (lvl>0) + printf("%*s", lvl*4, "\\_"); + assert(current->pinfo.pstat); + printf(" %s\n", current->pinfo.pstat->comm); + + if (!current->childs) + continue; + + mx_proc_tree_node_print_debug(current->childs, lvl+(current->parent != NULL)); + } + + return 0; +} + +int mx_proc_tree_print_debug(struct mx_proc_tree *pt) +{ + assert(pt); + printf("%7s %7s %7s %7s %15s %15s %7s COMMAND\n", + "PID", + "PPID", + "PGRP", + "SESSION", + "RSS", + "SUMRSS", + "THREADS"); + mx_proc_tree_node_print_debug(pt->root, 0); + return 0; +} + +int main(void) +{ + int res; + struct mx_proc_tree *pt = NULL; + + res = mx_proc_tree(&pt); + assert(res == 0); + + mx_proc_tree_print_debug(pt); + + mx_proc_tree_free(&pt); + + + return 0; + +} From 875002aead967904321a318754e7ce5dc38d46fa Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Fri, 23 Oct 2015 14:41:23 +0200 Subject: [PATCH 12/34] mx_proc: Use pgrp in addition to ppid to group processes --- mx_proc.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/mx_proc.c b/mx_proc.c index 611cda8b..1739ae84 100644 --- a/mx_proc.c +++ b/mx_proc.c @@ -269,11 +269,11 @@ static struct mx_proc_tree_node *mx_proc_tree_add(struct mx_proc_tree *pt, struc /* new is second to last roots parent? -> collect */ current = pt->root; while (current->next) { - if (current->next->pinfo.pstat->ppid != new->pinfo.pstat->pid) { + if (ppid_or_pgrp(current->next->pinfo.pstat) != new->pinfo.pstat->pid) { current = current->next; continue; } - assert(current->next->pinfo.pstat->ppid == new->pinfo.pstat->pid); + assert(ppid_or_pgrp(current->next->pinfo.pstat) == new->pinfo.pstat->pid); /* disconnect next */ next = current->next; @@ -286,7 +286,7 @@ static struct mx_proc_tree_node *mx_proc_tree_add(struct mx_proc_tree *pt, struc } /* new is first roots parent? -> new is new root */ - if (pt->root->pinfo.pstat->ppid == new->pinfo.pstat->pid) { + if (ppid_or_pgrp(pt->root->pinfo.pstat)== new->pinfo.pstat->pid) { assert(!new->next); current = pt->root; @@ -303,8 +303,7 @@ static struct mx_proc_tree_node *mx_proc_tree_add(struct mx_proc_tree *pt, struc } } - - parent = mx_proc_tree_find_by_pid(pt->root, new->pinfo.pstat->ppid); + parent = mx_proc_tree_find_by_pid(pt->root, ppid_or_pgrp(new->pinfo.pstat)); if (parent) { new->parent = parent; mx_proc_tree_add_to_list_sorted(&parent->childs, new); From 0381a76040573368b8c0d3df5da5e5e7e2286645 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Fri, 23 Oct 2015 23:37:17 +0200 Subject: [PATCH 13/34] mxqd: Kill jobs over memory at most every 60 seconds this resolves https://github.molgen.mpg.de/mariux64/mxq/issues/16 --- mxqd.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ mxqd.h | 2 ++ 2 files changed, 67 insertions(+) diff --git a/mxqd.c b/mxqd.c index 09b8c5ba..b15d558f 100644 --- a/mxqd.c +++ b/mxqd.c @@ -1574,6 +1574,69 @@ int killall_over_time(struct mxq_server *server) return 0; } +int killall_over_memory(struct mxq_server *server) +{ + struct mxq_user_list *user; + struct mxq_group_list *group; + struct mxq_job_list *job; + struct mx_proc_tree *pt = NULL; + struct mx_proc_info *pinfo; + long pagesize; + pid_t pid; + unsigned long long int memory; + int res; + + assert(server); + + if (!server->jobs_running) + return 0; + + /* limit killing to every >= 10 seconds */ + mx_within_rate_limit_or_return(10, 0); + + pagesize = sysconf(_SC_PAGESIZE); + if (!pagesize) { + mx_log_warning("killall_over_memory(): Can't get _SC_PAGESIZE. Assuming 4096."); + pagesize = 4096; + } + + res = mx_proc_tree(&pt); + if (res < 0) { + mx_log_err("killall_over_memory(): Reading process tree failed: %m"); + return res; + } + + for (user=server->users; user; user=user->next) { + for (group=user->groups; group; group=group->next) { + for (job=group->jobs; job; job=job->next) { + pid = job->job.host_pid; + + pinfo = mx_proc_tree_proc_info(pt, pid); + if (!pinfo) { + mx_log_warning("killall_over_memory(): Can't find process with pid %llu in process tree", pid); + continue; + } + + memory = pinfo->sum_rss * pagesize / 1024 / 1024; + + if (job->max_sum_rss < memory) + job->max_sum_rss = memory; + + if (memory <= group->group.job_memory) + continue; + + mx_log_info("killall_over_memory(): used(%llu) > requested(%llu): Sending signal=KILL to job=%s(%d):%lu:%lu pgrp=%d", + memory, group->group.job_memory, + group->group.user_name, group->group.user_uid, group->group.group_id, job->job.job_id, pid); + + kill(-pid, SIGKILL); + } + } + } + mx_proc_tree_free(&pt); + return 0; +} + int killallcancelled(struct mxq_server *server, int sig, unsigned int pgrp) { struct mxq_user_list *user; @@ -1867,6 +1930,7 @@ int main(int argc, char *argv[]) killallcancelled(&server, SIGTERM, 0); killallcancelled(&server, SIGINT, 0); killall_over_time(&server); + killall_over_memory(&server); if (!server.group_cnt) { assert(!server.jobs_running); @@ -1914,6 +1978,7 @@ int main(int argc, char *argv[]) killallcancelled(&server, SIGTERM, 0); killallcancelled(&server, SIGINT, 0); killall_over_time(&server); + killall_over_memory(&server); mx_log_info("jobs_running=%lu global_sigint_cnt=%d global_sigterm_cnt=%d : Exiting. Wating for jobs to finish. Sleeping for a while.", server.jobs_running, global_sigint_cnt, global_sigterm_cnt); diff --git a/mxqd.h b/mxqd.h index 4de72d44..4bc1cd0a 100644 --- a/mxqd.h +++ b/mxqd.h @@ -10,6 +10,8 @@ struct mxq_job_list { struct mxq_job job; + unsigned long long int max_sum_rss; + pid_t pid; }; From 7179a66864b83c063c642ad6d13cc813c4cf69fb Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Sat, 24 Oct 2015 19:45:10 +0200 Subject: [PATCH 14/34] mysql: Drop tables and triggers only if they exist --- mysql/create_tables.sql | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/mysql/create_tables.sql b/mysql/create_tables.sql index ce129e4f..8b096a71 100644 --- a/mysql/create_tables.sql +++ b/mysql/create_tables.sql @@ -1,5 +1,5 @@ -DROP TABLE mxq_group; +DROP TABLE IF EXISTS mxq_group; CREATE TABLE IF NOT EXISTS mxq_group ( group_id INT8 UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, group_name VARCHAR(511) NOT NULL DEFAULT 'default', @@ -62,7 +62,7 @@ CREATE TABLE IF NOT EXISTS mxq_group ( INDEX(group_name) ); -DROP TABLE mxq_job; +DROP TABLE IF EXISTS mxq_job; CREATE TABLE IF NOT EXISTS mxq_job ( job_id INT8 UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, job_status INT2 UNSIGNED NOT NULL DEFAULT 0, @@ -123,7 +123,7 @@ CREATE TABLE IF NOT EXISTS mxq_job ( INDEX (server_id(767)) ); -DROP TABLE mxq_server; +DROP TABLE IF EXISTS mxq_server; CREATE TABLE IF NOT EXISTS mxq_server ( host_id INT4 UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, host_hostname VARCHAR(511) NOT NULL DEFAULT 'localhost', @@ -143,11 +143,9 @@ CREATE TABLE IF NOT EXISTS mxq_server ( server_stop TIMESTAMP DEFAULT 0 ); - - LOCK TABLES mxq_job WRITE, mxq_group WRITE; DELIMITER | -DROP TRIGGER mxq_add_group| +DROP TRIGGER IF EXISTS mxq_add_group| CREATE TRIGGER mxq_add_group BEFORE INSERT ON mxq_group FOR EACH ROW BEGIN SET NEW.group_mtime = NOW(); @@ -159,7 +157,7 @@ CREATE TRIGGER mxq_add_group BEFORE INSERT ON mxq_group END IF; END; | -DROP TRIGGER mxq_update_group| +DROP TRIGGER IF EXISTS mxq_update_group| CREATE TRIGGER mxq_update_group BEFORE UPDATE ON mxq_group FOR EACH ROW BEGIN SET NEW.group_mtime = NOW(); @@ -180,7 +178,7 @@ CREATE TRIGGER mxq_update_group BEFORE UPDATE ON mxq_group END IF; END; | -DROP TRIGGER mxq_add_job| +DROP TRIGGER IF EXISTS mxq_add_job| CREATE TRIGGER mxq_add_job AFTER INSERT ON mxq_job FOR EACH ROW BEGIN UPDATE mxq_group SET @@ -190,7 +188,7 @@ CREATE TRIGGER mxq_add_job AFTER INSERT ON mxq_job WHERE group_id=NEW.group_id; END; | -DROP TRIGGER mxq_update_job| +DROP TRIGGER IF EXISTS mxq_update_job| CREATE TRIGGER mxq_update_job BEFORE UPDATE ON mxq_job FOR EACH ROW BEGIN IF NEW.job_status != OLD.job_status THEN From cce9159237394e3255d682ebc39c8bbde734f2fd Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Sat, 24 Oct 2015 19:49:50 +0200 Subject: [PATCH 15/34] mysql: Split create_tables into create_tables, drop_tables and create_trigger --- mysql/create_tables.sql | 135 --------------------------------------- mysql/create_trigger.sql | 130 +++++++++++++++++++++++++++++++++++++ mysql/drop_tables.sql | 3 + 3 files changed, 133 insertions(+), 135 deletions(-) create mode 100644 mysql/create_trigger.sql create mode 100644 mysql/drop_tables.sql diff --git a/mysql/create_tables.sql b/mysql/create_tables.sql index 8b096a71..978c679f 100644 --- a/mysql/create_tables.sql +++ b/mysql/create_tables.sql @@ -1,5 +1,3 @@ - -DROP TABLE IF EXISTS mxq_group; CREATE TABLE IF NOT EXISTS mxq_group ( group_id INT8 UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, group_name VARCHAR(511) NOT NULL DEFAULT 'default', @@ -62,7 +60,6 @@ CREATE TABLE IF NOT EXISTS mxq_group ( INDEX(group_name) ); -DROP TABLE IF EXISTS mxq_job; CREATE TABLE IF NOT EXISTS mxq_job ( job_id INT8 UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, job_status INT2 UNSIGNED NOT NULL DEFAULT 0, @@ -123,7 +120,6 @@ CREATE TABLE IF NOT EXISTS mxq_job ( INDEX (server_id(767)) ); -DROP TABLE IF EXISTS mxq_server; CREATE TABLE IF NOT EXISTS mxq_server ( host_id INT4 UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, host_hostname VARCHAR(511) NOT NULL DEFAULT 'localhost', @@ -142,134 +138,3 @@ CREATE TABLE IF NOT EXISTS mxq_server ( server_start TIMESTAMP DEFAULT 0, server_stop TIMESTAMP DEFAULT 0 ); - -LOCK TABLES mxq_job WRITE, mxq_group WRITE; -DELIMITER | -DROP TRIGGER IF EXISTS mxq_add_group| -CREATE TRIGGER mxq_add_group BEFORE INSERT ON mxq_group - FOR EACH ROW BEGIN - SET NEW.group_mtime = NOW(); - - IF (NEW.group_jobs_running = 0 AND NEW.group_jobs_inq = 0) THEN - SET NEW.group_date_end = NEW.group_mtime; - ELSEIF (NEW.group_jobs_running > 0 OR NEW.group_jobs_inq > 0) THEN - SET NEW.group_date_end = 0; - END IF; - END; -| -DROP TRIGGER IF EXISTS mxq_update_group| -CREATE TRIGGER mxq_update_group BEFORE UPDATE ON mxq_group - FOR EACH ROW BEGIN - SET NEW.group_mtime = NOW(); - - IF OLD.group_jobs_inq > 0 AND OLD.group_jobs_running = 0 THEN - SET NEW.stats_wait_sec = OLD.stats_wait_sec + (UNIX_TIMESTAMP(NEW.group_mtime) - UNIX_TIMESTAMP(OLD.group_mtime)); - ELSEIF OLD.group_jobs_running > 0 THEN - SET NEW.stats_run_sec = OLD.stats_run_sec + (UNIX_TIMESTAMP(NEW.group_mtime) - UNIX_TIMESTAMP(OLD.group_mtime)); - END IF; - - IF (NEW.group_jobs_running = 0 AND NEW.group_jobs_inq = 0) AND - (OLD.group_jobs_running > 0 OR OLD.group_jobs_inq > 0) THEN - SET NEW.group_date_end = NEW.group_mtime; - ELSEIF (OLD.group_jobs_running = 0 AND OLD.group_jobs_inq = 0) AND - (NEW.group_jobs_running > 0 OR NEW.group_jobs_inq > 0) THEN - SET NEW.stats_idle_sec = OLD.stats_idle_sec + (UNIX_TIMESTAMP(NEW.group_mtime) - UNIX_TIMESTAMP(OLD.group_date_end)); - SET NEW.group_date_end = 0; - END IF; - END; -| -DROP TRIGGER IF EXISTS mxq_add_job| -CREATE TRIGGER mxq_add_job AFTER INSERT ON mxq_job - FOR EACH ROW BEGIN - UPDATE mxq_group SET - group_jobs=group_jobs+1, - group_jobs_inq=group_jobs_inq+1, - group_mtime=NULL - WHERE group_id=NEW.group_id; - END; -| -DROP TRIGGER IF EXISTS mxq_update_job| -CREATE TRIGGER mxq_update_job BEFORE UPDATE ON mxq_job - FOR EACH ROW BEGIN - IF NEW.job_status != OLD.job_status THEN - IF NEW.job_status IN (150, 200) AND OLD.job_status IN (0, 100) THEN - UPDATE mxq_group SET - group_jobs_inq=group_jobs_inq-1, - group_jobs_running=group_jobs_running+1, - group_slots_running=group_slots_running+NEW.host_slots, - group_mtime=NULL - WHERE group_id=NEW.group_id; - ELSEIF NEW.job_status = 200 AND OLD.job_status = 150 THEN - UPDATE mxq_group SET - group_slots_running=group_slots_running-OLD.host_slots+NEW.host_slots, - group_mtime=NULL - WHERE group_id=NEW.group_id; - ELSEIF NEW.job_status IN (400, 750) AND OLD.job_status IN (150, 200, 250, 300, 350, 399) THEN - UPDATE mxq_group SET - group_slots_running=group_slots_running-NEW.host_slots, - group_jobs_running=group_jobs_running-1, - group_jobs_failed=group_jobs_failed+1, - stats_max_maxrss=GREATEST(stats_max_maxrss, NEW.stats_maxrss), - stats_max_utime_sec=GREATEST(stats_max_utime_sec, NEW.stats_utime_sec), - stats_max_stime_sec=GREATEST(stats_max_stime_sec, NEW.stats_stime_sec), - stats_max_real_sec=GREATEST(stats_max_real_sec, NEW.stats_real_sec), - stats_total_utime_sec=stats_total_utime_sec+NEW.stats_utime_sec, - stats_total_stime_sec=stats_total_stime_sec+NEW.stats_stime_sec, - stats_total_real_sec=stats_total_real_sec+NEW.stats_real_sec, - group_mtime=NULL - WHERE group_id=NEW.group_id; - ELSEIF NEW.job_status = 990 AND OLD.job_status IN (0, 100, 989) THEN - SET NEW.date_start = NOW(); - SET NEW.date_end = NEW.date_start; - UPDATE mxq_group SET - group_jobs_inq=group_jobs_inq-1, - group_jobs_cancelled=group_jobs_cancelled+1, - group_mtime=NULL - WHERE group_id=NEW.group_id; - ELSEIF NEW.job_status = 999 AND OLD.job_status IN (150, 200, 250, 399) THEN - UPDATE mxq_group SET - group_slots_running=group_slots_running-NEW.host_slots, - group_jobs_running=group_jobs_running-1, - group_jobs_unknown=group_jobs_unknown+1, - group_mtime=NULL - WHERE group_id=NEW.group_id; - ELSEIF NEW.job_status = 999 AND OLD.job_status IN (400, 750, 755) THEN - UPDATE mxq_group SET - group_jobs_failed=group_jobs_failed-1, - group_jobs_unknown=group_jobs_unknown+1, - group_mtime=NULL - WHERE group_id=NEW.group_id; - ELSEIF NEW.job_status = 1000 AND OLD.job_status IN (150, 200, 250, 300, 350, 399) THEN - UPDATE mxq_group SET - group_slots_running=group_slots_running-NEW.host_slots, - group_jobs_running=group_jobs_running-1, - group_jobs_finished=group_jobs_finished+1, - stats_max_maxrss=GREATEST(stats_max_maxrss, NEW.stats_maxrss), - stats_max_utime_sec=GREATEST(stats_max_utime_sec, NEW.stats_utime_sec), - stats_max_stime_sec=GREATEST(stats_max_stime_sec, NEW.stats_stime_sec), - stats_max_real_sec=GREATEST(stats_max_real_sec, NEW.stats_real_sec), - stats_total_utime_sec=stats_total_utime_sec+NEW.stats_utime_sec, - stats_total_stime_sec=stats_total_stime_sec+NEW.stats_stime_sec, - stats_total_real_sec=stats_total_real_sec+NEW.stats_real_sec, - stats_total_utime_sec_finished=stats_total_utime_sec_finished+NEW.stats_utime_sec, - stats_total_stime_sec_finished=stats_total_stime_sec_finished+NEW.stats_stime_sec, - stats_total_real_sec_finished=stats_total_real_sec_finished+NEW.stats_real_sec, - group_mtime=NULL - WHERE group_id=NEW.group_id; - ELSEIF NEW.job_status NOT IN (399, 755, 989, 990) THEN - UPDATE mxq_group SET - stats_max_maxrss=GREATEST(stats_max_maxrss, NEW.stats_maxrss), - stats_max_utime_sec=GREATEST(stats_max_utime_sec, NEW.stats_utime_sec), - stats_max_stime_sec=GREATEST(stats_max_stime_sec, NEW.stats_stime_sec), - stats_max_real_sec=GREATEST(stats_max_real_sec, NEW.stats_real_sec), - stats_total_utime_sec=stats_total_utime_sec+NEW.stats_utime_sec, - stats_total_stime_sec=stats_total_stime_sec+NEW.stats_stime_sec, - stats_total_real_sec=stats_total_real_sec+NEW.stats_real_sec, - group_mtime=NULL - WHERE group_id=NEW.group_id; - END IF; - END IF; - END; -| -DELIMITER ; -UNLOCK TABLES; diff --git a/mysql/create_trigger.sql b/mysql/create_trigger.sql new file mode 100644 index 00000000..ccd2af6e --- /dev/null +++ b/mysql/create_trigger.sql @@ -0,0 +1,130 @@ +LOCK TABLES mxq_job WRITE, mxq_group WRITE; +DELIMITER | +DROP TRIGGER IF EXISTS mxq_add_group| +CREATE TRIGGER mxq_add_group BEFORE INSERT ON mxq_group + FOR EACH ROW BEGIN + SET NEW.group_mtime = NOW(); + + IF (NEW.group_jobs_running = 0 AND NEW.group_jobs_inq = 0) THEN + SET NEW.group_date_end = NEW.group_mtime; + ELSEIF (NEW.group_jobs_running > 0 OR NEW.group_jobs_inq > 0) THEN + SET NEW.group_date_end = 0; + END IF; + END; +| +DROP TRIGGER IF EXISTS mxq_update_group| +CREATE TRIGGER mxq_update_group BEFORE UPDATE ON mxq_group + FOR EACH ROW BEGIN + SET NEW.group_mtime = NOW(); + + IF OLD.group_jobs_inq > 0 AND OLD.group_jobs_running = 0 THEN + SET NEW.stats_wait_sec = OLD.stats_wait_sec + (UNIX_TIMESTAMP(NEW.group_mtime) - UNIX_TIMESTAMP(OLD.group_mtime)); + ELSEIF OLD.group_jobs_running > 0 THEN + SET NEW.stats_run_sec = OLD.stats_run_sec + (UNIX_TIMESTAMP(NEW.group_mtime) - UNIX_TIMESTAMP(OLD.group_mtime)); + END IF; + + IF (NEW.group_jobs_running = 0 AND NEW.group_jobs_inq = 0) AND + (OLD.group_jobs_running > 0 OR OLD.group_jobs_inq > 0) THEN + SET NEW.group_date_end = NEW.group_mtime; + ELSEIF (OLD.group_jobs_running = 0 AND OLD.group_jobs_inq = 0) AND + (NEW.group_jobs_running > 0 OR NEW.group_jobs_inq > 0) THEN + SET NEW.stats_idle_sec = OLD.stats_idle_sec + (UNIX_TIMESTAMP(NEW.group_mtime) - UNIX_TIMESTAMP(OLD.group_date_end)); + SET NEW.group_date_end = 0; + END IF; + END; +| +DROP TRIGGER IF EXISTS mxq_add_job| +CREATE TRIGGER mxq_add_job AFTER INSERT ON mxq_job + FOR EACH ROW BEGIN + UPDATE mxq_group SET + group_jobs=group_jobs+1, + group_jobs_inq=group_jobs_inq+1, + group_mtime=NULL + WHERE group_id=NEW.group_id; + END; +| +DROP TRIGGER IF EXISTS mxq_update_job| +CREATE TRIGGER mxq_update_job BEFORE UPDATE ON mxq_job + FOR EACH ROW BEGIN + IF NEW.job_status != OLD.job_status THEN + IF NEW.job_status IN (150, 200) AND OLD.job_status IN (0, 100) THEN + UPDATE mxq_group SET + group_jobs_inq=group_jobs_inq-1, + group_jobs_running=group_jobs_running+1, + group_slots_running=group_slots_running+NEW.host_slots, + group_mtime=NULL + WHERE group_id=NEW.group_id; + ELSEIF NEW.job_status = 200 AND OLD.job_status = 150 THEN + UPDATE mxq_group SET + group_slots_running=group_slots_running-OLD.host_slots+NEW.host_slots, + group_mtime=NULL + WHERE group_id=NEW.group_id; + ELSEIF NEW.job_status IN (400, 750) AND OLD.job_status IN (150, 200, 250, 300, 350, 399) THEN + UPDATE mxq_group SET + group_slots_running=group_slots_running-NEW.host_slots, + group_jobs_running=group_jobs_running-1, + group_jobs_failed=group_jobs_failed+1, + stats_max_maxrss=GREATEST(stats_max_maxrss, NEW.stats_maxrss), + stats_max_utime_sec=GREATEST(stats_max_utime_sec, NEW.stats_utime_sec), + stats_max_stime_sec=GREATEST(stats_max_stime_sec, NEW.stats_stime_sec), + stats_max_real_sec=GREATEST(stats_max_real_sec, NEW.stats_real_sec), + stats_total_utime_sec=stats_total_utime_sec+NEW.stats_utime_sec, + stats_total_stime_sec=stats_total_stime_sec+NEW.stats_stime_sec, + stats_total_real_sec=stats_total_real_sec+NEW.stats_real_sec, + group_mtime=NULL + WHERE group_id=NEW.group_id; + ELSEIF NEW.job_status = 990 AND OLD.job_status IN (0, 100, 989) THEN + SET NEW.date_start = NOW(); + SET NEW.date_end = NEW.date_start; + UPDATE mxq_group SET + group_jobs_inq=group_jobs_inq-1, + group_jobs_cancelled=group_jobs_cancelled+1, + group_mtime=NULL + WHERE group_id=NEW.group_id; + ELSEIF NEW.job_status = 999 AND OLD.job_status IN (150, 200, 250, 399) THEN + UPDATE mxq_group SET + group_slots_running=group_slots_running-NEW.host_slots, + group_jobs_running=group_jobs_running-1, + group_jobs_unknown=group_jobs_unknown+1, + group_mtime=NULL + WHERE group_id=NEW.group_id; + ELSEIF NEW.job_status = 999 AND OLD.job_status IN (400, 750, 755) THEN + UPDATE mxq_group SET + group_jobs_failed=group_jobs_failed-1, + group_jobs_unknown=group_jobs_unknown+1, + group_mtime=NULL + WHERE group_id=NEW.group_id; + ELSEIF NEW.job_status = 1000 AND OLD.job_status IN (150, 200, 250, 300, 350, 399) THEN + UPDATE mxq_group SET + group_slots_running=group_slots_running-NEW.host_slots, + group_jobs_running=group_jobs_running-1, + group_jobs_finished=group_jobs_finished+1, + stats_max_maxrss=GREATEST(stats_max_maxrss, NEW.stats_maxrss), + stats_max_utime_sec=GREATEST(stats_max_utime_sec, NEW.stats_utime_sec), + stats_max_stime_sec=GREATEST(stats_max_stime_sec, NEW.stats_stime_sec), + stats_max_real_sec=GREATEST(stats_max_real_sec, NEW.stats_real_sec), + stats_total_utime_sec=stats_total_utime_sec+NEW.stats_utime_sec, + stats_total_stime_sec=stats_total_stime_sec+NEW.stats_stime_sec, + stats_total_real_sec=stats_total_real_sec+NEW.stats_real_sec, + stats_total_utime_sec_finished=stats_total_utime_sec_finished+NEW.stats_utime_sec, + stats_total_stime_sec_finished=stats_total_stime_sec_finished+NEW.stats_stime_sec, + stats_total_real_sec_finished=stats_total_real_sec_finished+NEW.stats_real_sec, + group_mtime=NULL + WHERE group_id=NEW.group_id; + ELSEIF NEW.job_status NOT IN (399, 755, 989, 990) THEN + UPDATE mxq_group SET + stats_max_maxrss=GREATEST(stats_max_maxrss, NEW.stats_maxrss), + stats_max_utime_sec=GREATEST(stats_max_utime_sec, NEW.stats_utime_sec), + stats_max_stime_sec=GREATEST(stats_max_stime_sec, NEW.stats_stime_sec), + stats_max_real_sec=GREATEST(stats_max_real_sec, NEW.stats_real_sec), + stats_total_utime_sec=stats_total_utime_sec+NEW.stats_utime_sec, + stats_total_stime_sec=stats_total_stime_sec+NEW.stats_stime_sec, + stats_total_real_sec=stats_total_real_sec+NEW.stats_real_sec, + group_mtime=NULL + WHERE group_id=NEW.group_id; + END IF; + END IF; + END; +| +DELIMITER ; +UNLOCK TABLES; diff --git a/mysql/drop_tables.sql b/mysql/drop_tables.sql new file mode 100644 index 00000000..5ff48f17 --- /dev/null +++ b/mysql/drop_tables.sql @@ -0,0 +1,3 @@ +DROP TABLE IF EXISTS mxq_group; +DROP TABLE IF EXISTS mxq_job; +DROP TABLE IF EXISTS mxq_server; From f87e85147c5d14e2f586dd8321fdf82f8795d3df Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Sat, 24 Oct 2015 20:35:05 +0200 Subject: [PATCH 16/34] README: Update mysql section --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6dfb2602..93d26326 100644 --- a/README.md +++ b/README.md @@ -32,12 +32,17 @@ bee update mxq ``` ## Initial setup -Definitions of the tables and triggers for the MySQL database can be found in +Definitions of the tables for the MySQL database can be found in [mysql/create_tables.sql](https://github.molgen.mpg.de/mariux64/mxq/blob/master/mysql/create_tables.sql) +and +[mysql/create_trigger.sql](https://github.molgen.mpg.de/mariux64/mxq/blob/master/mysql/create_trigger.sql) Be sure to create those once and check the same [directory for alter_tables*.sql`](https://github.molgen.mpg.de/mariux64/mxq/blob/master/mysql/) files when upgrading. - +``` +mysql [options] [database] Date: Mon, 26 Oct 2015 10:37:08 +0100 Subject: [PATCH 17/34] test_mx_util: Fix renamed function --- test_mx_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_mx_util.c b/test_mx_util.c index 817fbef5..06cfe728 100644 --- a/test_mx_util.c +++ b/test_mx_util.c @@ -345,7 +345,7 @@ static void test_mx_strscan(void) assert(pps->ppid == getppid()); assert(pps->state == 'R'); assert(mx_streq(pps->comm, program_invocation_short_name) || mx_streq(pps->comm, "memcheck-amd64-")); - mx_proc_pid_stat_free(pps); + mx_proc_pid_stat_free_content(pps); } static void test_mx_strvec() { From 8b36941f6563f8ad91ab094b4b09627096bdf94f Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 26 Oct 2015 10:38:00 +0100 Subject: [PATCH 18/34] mx_log: Fix return value of mx_log_printf() --- mx_log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mx_log.c b/mx_log.c index 8ed95884..e9332b3e 100644 --- a/mx_log.c +++ b/mx_log.c @@ -87,7 +87,7 @@ int mx_log_printf(const char *fmt, ...) res = fflush(stderr); mx_free_null(msg); - if (len2 != len) + if (len2 != len+1) return -(errno=EIO); if (!res) From 68e8a199a8f1ac925df44c8638cc283b1a98b62d Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 26 Oct 2015 10:28:05 +0100 Subject: [PATCH 19/34] mx_log: Add mx_logva*() to use va lists when logging --- mx_log.c | 17 +++++++++++++---- mx_log.h | 11 +++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/mx_log.c b/mx_log.c index e9332b3e..ba5a8d55 100644 --- a/mx_log.c +++ b/mx_log.c @@ -137,12 +137,11 @@ static int log_log(int level, int loglevel, char *file, unsigned long line, cons return mx_log_printf("%s%s", prefix, msg); } -int mx_log_do(int level, char *file, unsigned long line, const char *func, const char *fmt, ...) +int mx_logva_do(int level, char *file, unsigned long line, const char *func, const char *fmt, va_list ap) { int loglevel; int len; char *msg = NULL; - va_list ap; int res; int preserved_errno = errno; @@ -153,9 +152,7 @@ int mx_log_do(int level, char *file, unsigned long line, const char *func, const return 0; } - va_start(ap, fmt); len = vasprintf(&msg, fmt, ap); - va_end(ap); if (len == -1) { errno = preserved_errno; @@ -173,6 +170,18 @@ int mx_log_do(int level, char *file, unsigned long line, const char *func, const return res; } +int mx_log_do(int level, char *file, unsigned long line, const char *func, const char *fmt, ...) +{ + va_list ap; + int res; + + va_start(ap, fmt); + res = mx_logva_do(level, file, line, func, fmt, ap); + va_end(ap); + + return res; +} + int mx_log_finish(void) { if (mx_log_log) diff --git a/mx_log.h b/mx_log.h index 48c60988..8b17631f 100644 --- a/mx_log.h +++ b/mx_log.h @@ -22,6 +22,7 @@ #define MX_LOG_DEBUG MX_LOG_SYSLOG_TO_MXLOG(LOG_DEBUG) /* debug-level messages */ #define mx_log(level, fmt, ...) mx_log_do((level), __FILE__, __LINE__, __func__, (fmt), ##__VA_ARGS__) +#define mx_logva(level, fmt, ap) mx_logva_do((level), __FILE__, __LINE__, __func__, (fmt), (ap)) #define mx_log_fatal(fmt, ...) mx_log(MX_LOG_EMERG, (fmt), ##__VA_ARGS__) #define mx_log_emerg(fmt, ...) mx_log(MX_LOG_EMERG, (fmt), ##__VA_ARGS__) @@ -33,6 +34,16 @@ #define mx_log_info(fmt, ...) mx_log(MX_LOG_INFO, (fmt), ##__VA_ARGS__) #define mx_log_debug(fmt, ...) mx_log(MX_LOG_DEBUG, (fmt), ##__VA_ARGS__) +#define mx_logva_fatal(fmt, ap) mx_log(MX_LOG_EMERG, (fmt), (ap)) +#define mx_logva_emerg(fmt, ap) mx_log(MX_LOG_EMERG, (fmt), (ap)) +#define mx_logva_alert(fmt, ap) mx_log(MX_LOG_ALERT, (fmt), (ap)) +#define mx_logva_crit(fmt, ap) mx_log(MX_LOG_CRIT, (fmt), (ap)) +#define mx_logva_err(fmt, ap) mx_log(MX_LOG_ERR, (fmt), (ap)) +#define mx_logva_warning(fmt, ap) mx_log(MX_LOG_WARNING, (fmt), (ap)) +#define mx_logva_notice(fmt, ap) mx_log(MX_LOG_NOTICE, (fmt), (ap)) +#define mx_logva_info(fmt, ap) mx_log(MX_LOG_INFO, (fmt), (ap)) +#define mx_logva_debug(fmt, ap) mx_log(MX_LOG_DEBUG, (fmt), (ap)) + int mx_log_log(int level, int loglevel, char *file, unsigned long line, const char *func, const char *msg) __attribute__ ((weak)); int mx_log_print(char *msg, size_t len) __attribute__ ((weak)); From bc32b56ee5cc251bfbcad08e9ff1789fce81be93 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 26 Oct 2015 10:47:07 +0100 Subject: [PATCH 20/34] README: update install section --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 93d26326..2e3f3970 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,11 @@ https://github.com/mariux/mxq ## Installation ### Install using `GNU make` ``` -make make install ``` + +or to specify a prefix: ``` -make PREFIX=... make PREFIX=... [DESTDIR=...] install ``` ### Install using `bee` @@ -26,6 +26,8 @@ make PREFIX=... [DESTDIR=...] install bee init $(bee download git://github.molgen.mpg.de/mariux64/mxq.git) --execute bee update mxq ``` + +or to specify a prefix ``` bee init $(bee download git://github.molgen.mpg.de/mariux64/mxq.git) --prefix=... --execute bee update mxq From b57816c4a72379f967310691984856ecfb555f79 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 26 Oct 2015 11:20:13 +0100 Subject: [PATCH 21/34] mxq_log: Use mx_streq() --- mxq_log.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mxq_log.c b/mxq_log.c index d59ffac7..77b40b5f 100644 --- a/mxq_log.c +++ b/mxq_log.c @@ -8,6 +8,8 @@ #include #include "mx_log.h" +#include "mx_util.h" + #ifndef mx_free_null #include #define mx_free_null(a) do { free((a)); (a) = NULL; } while(0) @@ -42,7 +44,6 @@ static int timetag(char *buf, size_t size) int mx_log_print(char *msg, size_t len) { - int res; char timebuf[1024]; static char *lastmsg = NULL; @@ -61,8 +62,7 @@ int mx_log_print(char *msg, size_t len) return -(errno=EINVAL); if (lastmsg && lastlen == len) { - res = strcmp(msg, lastmsg); - if (res == 0) { + if (mx_streq(msg, lastmsg)) { cnt++; mx_free_null(msg); return 2; From 379116434fe9c9e4f98167d064f7e029741b7e50 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 26 Oct 2015 11:40:40 +0100 Subject: [PATCH 22/34] mx_log: Fix typo "ALERT" --- mx_log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mx_log.c b/mx_log.c index ba5a8d55..6a6a5b53 100644 --- a/mx_log.c +++ b/mx_log.c @@ -109,7 +109,7 @@ static int log_log(int level, int loglevel, char *file, unsigned long line, cons prefix = "EMERGENCY: "; break; case MX_LOG_ALERT: - prefix = "AKERT: "; + prefix = "ALERT: "; break; case MX_LOG_CRIT: prefix = "CRITCAL ERROR: "; From e345231577705b9fc94a6c4e39a292bd7fa1b329 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 26 Oct 2015 13:54:18 +0100 Subject: [PATCH 23/34] Makefile: Build and run tests by default --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a9f58467..b6b0e805 100644 --- a/Makefile +++ b/Makefile @@ -186,7 +186,7 @@ manpages/%: manpages/%.xml .PHONY: all .PHONY: build -all: build +all: build test .PHONY: devel devel: CFLAGS += -DMXQ_DEVELOPMENT From 9509e6eb3b23c1b5bb2c4a5e597c0c67a6b1b8f3 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 26 Oct 2015 13:09:52 +0100 Subject: [PATCH 24/34] mxq_job: Minor cleanup --- mxq_job.c | 54 ++++++++++++++++++++++-------------------------------- 1 file changed, 22 insertions(+), 32 deletions(-) diff --git a/mxq_job.c b/mxq_job.c index 68fc709d..f894f22b 100644 --- a/mxq_job.c +++ b/mxq_job.c @@ -23,37 +23,31 @@ " job_flags, " \ " job_priority, " \ " group_id, " \ - \ " job_workdir, " \ " job_argc, " \ " job_argv, " \ " job_stdout, " \ " job_stderr, " \ - \ " job_umask, " \ " host_submit, " \ " host_id, " \ " server_id, " \ " host_hostname, " \ - \ " host_pid, " \ " host_slots, " \ " UNIX_TIMESTAMP(date_submit) as date_submit, " \ " UNIX_TIMESTAMP(date_start) as date_start, " \ " UNIX_TIMESTAMP(date_end) as date_end, " \ - \ " 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, " \ @@ -73,37 +67,31 @@ static int bind_result_job_fields(struct mx_mysql_bind *result, struct mxq_job * res += mx_mysql_bind_var(result, idx++, uint64, &(j->job_flags)); res += mx_mysql_bind_var(result, idx++, uint16, &(j->job_priority)); res += mx_mysql_bind_var(result, idx++, uint64, &(j->group_id)); - res += mx_mysql_bind_var(result, idx++, string, &(j->job_workdir)); res += mx_mysql_bind_var(result, idx++, uint16, &(j->job_argc)); res += mx_mysql_bind_var(result, idx++, string, &(j->job_argv_str)); res += mx_mysql_bind_var(result, idx++, string, &(j->job_stdout)); res += mx_mysql_bind_var(result, idx++, string, &(j->job_stderr)); - res += mx_mysql_bind_var(result, idx++, uint32, &(j->job_umask)); res += mx_mysql_bind_var(result, idx++, string, &(j->host_submit)); res += mx_mysql_bind_var(result, idx++, string, &(j->host_id)); res += mx_mysql_bind_var(result, idx++, string, &(j->server_id)); res += mx_mysql_bind_var(result, idx++, string, &(j->host_hostname)); - res += mx_mysql_bind_var(result, idx++, uint32, &(j->host_pid)); res += mx_mysql_bind_var(result, idx++, uint32, &(j->host_slots)); res += mx_mysql_bind_var(result, idx++, int64, &(j->date_submit)); res += mx_mysql_bind_var(result, idx++, int64, &(j->date_start)); res += mx_mysql_bind_var(result, idx++, int64, &(j->date_end)); - res += mx_mysql_bind_var(result, idx++, int32, &(j->stats_status)); res += mx_mysql_bind_var(result, idx++, int64, &(j->stats_rusage.ru_utime.tv_sec)); res += mx_mysql_bind_var(result, idx++, int64, &(j->stats_rusage.ru_utime.tv_usec)); res += mx_mysql_bind_var(result, idx++, int64, &(j->stats_rusage.ru_stime.tv_sec)); res += mx_mysql_bind_var(result, idx++, int64, &(j->stats_rusage.ru_stime.tv_usec)); - res += mx_mysql_bind_var(result, idx++, int64, &(j->stats_realtime.tv_sec)); res += mx_mysql_bind_var(result, idx++, int64, &(j->stats_realtime.tv_usec)); res += mx_mysql_bind_var(result, idx++, int64, &(j->stats_rusage.ru_maxrss)); res += mx_mysql_bind_var(result, idx++, int64, &(j->stats_rusage.ru_minflt)); res += mx_mysql_bind_var(result, idx++, int64, &(j->stats_rusage.ru_majflt)); - res += mx_mysql_bind_var(result, idx++, int64, &(j->stats_rusage.ru_nswap)); res += mx_mysql_bind_var(result, idx++, int64, &(j->stats_rusage.ru_inblock)); res += mx_mysql_bind_var(result, idx++, int64, &(j->stats_rusage.ru_oublock)); @@ -457,6 +445,7 @@ int mxq_set_job_status_running(struct mx_mysql *mysql, struct mxq_job *job) 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}; @@ -509,27 +498,28 @@ int mxq_set_job_status_exited(struct mx_mysql *mysql, struct mxq_job *job) res = mx_mysql_bind_init_param(¶m, 20); assert(res == 0); + idx = 0; res = 0; - res += mx_mysql_bind_var(¶m, 0, uint16, &(newstatus)); - res += mx_mysql_bind_var(¶m, 1, int32, &(job->stats_status)); - res += mx_mysql_bind_var(¶m, 2, int64, &(job->stats_rusage.ru_utime.tv_sec)); - res += mx_mysql_bind_var(¶m, 3, int64, &(job->stats_rusage.ru_utime.tv_usec)); - res += mx_mysql_bind_var(¶m, 4, int64, &(job->stats_rusage.ru_stime.tv_sec)); - res += mx_mysql_bind_var(¶m, 5, int64, &(job->stats_rusage.ru_stime.tv_usec)); - res += mx_mysql_bind_var(¶m, 6, int64, &(job->stats_realtime.tv_sec)); - res += mx_mysql_bind_var(¶m, 7, int64, &(job->stats_realtime.tv_usec)); - res += mx_mysql_bind_var(¶m, 8, int64, &(job->stats_rusage.ru_maxrss)); - res += mx_mysql_bind_var(¶m, 9, int64, &(job->stats_rusage.ru_minflt)); - res += mx_mysql_bind_var(¶m, 10, int64, &(job->stats_rusage.ru_majflt)); - res += mx_mysql_bind_var(¶m, 11, int64, &(job->stats_rusage.ru_nswap)); - res += mx_mysql_bind_var(¶m, 12, int64, &(job->stats_rusage.ru_inblock)); - res += mx_mysql_bind_var(¶m, 13, int64, &(job->stats_rusage.ru_oublock)); - res += mx_mysql_bind_var(¶m, 14, int64, &(job->stats_rusage.ru_nvcsw)); - res += mx_mysql_bind_var(¶m, 15, int64, &(job->stats_rusage.ru_nivcsw)); - res += mx_mysql_bind_var(¶m, 16, uint64, &(job->job_id)); - res += mx_mysql_bind_var(¶m, 17, string, &(job->host_hostname)); - res += mx_mysql_bind_var(¶m, 18, string, &(job->server_id)); - res += mx_mysql_bind_var(¶m, 19, uint32, &(job->host_pid)); + res += mx_mysql_bind_var(¶m, idx++, uint16, &(newstatus)); + res += mx_mysql_bind_var(¶m, idx++, int32, &(job->stats_status)); + res += mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_utime.tv_sec)); + res += mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_utime.tv_usec)); + res += mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_stime.tv_sec)); + res += mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_stime.tv_usec)); + res += mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_realtime.tv_sec)); + res += mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_realtime.tv_usec)); + res += mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_maxrss)); + res += mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_minflt)); + res += mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_majflt)); + res += mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_nswap)); + res += mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_inblock)); + res += mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_oublock)); + res += mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_nvcsw)); + res += mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_nivcsw)); + res += mx_mysql_bind_var(¶m, idx++, uint64, &(job->job_id)); + res += mx_mysql_bind_var(¶m, idx++, string, &(job->host_hostname)); + res += mx_mysql_bind_var(¶m, idx++, string, &(job->server_id)); + res += mx_mysql_bind_var(¶m, idx++, uint32, &(job->host_pid)); assert(res == 0); res = mx_mysql_do_statement_noresult_retry_on_fail(mysql, query, ¶m); From 9b2a5f47c845018c8d513e57fa32bf404f546f60 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 26 Oct 2015 13:51:07 +0100 Subject: [PATCH 25/34] mxqd: Store and use max_sumrss resolves parts of https://github.molgen.mpg.de/mariux64/mxq/issues/16 --- mxq_group.c | 4 +++- mxq_group.h | 1 + mxq_job.c | 8 ++++++-- mxq_job.h | 2 ++ mxqd.c | 10 +++++----- mxqdump.c | 8 ++++++-- mysql/alter_tables_0.17.0.sql | 11 +++++++++++ mysql/create_tables.sql | 4 ++++ mysql/create_trigger.sql | 3 +++ web/pages/mxq/mxq.in | 3 +++ 10 files changed, 44 insertions(+), 10 deletions(-) create mode 100644 mysql/alter_tables_0.17.0.sql diff --git a/mxq_group.c b/mxq_group.c index 2887411d..e9c0ac4d 100644 --- a/mxq_group.c +++ b/mxq_group.c @@ -12,7 +12,7 @@ #include "mx_util.h" #include "mx_mysql.h" -#define GROUP_FIELDS_CNT 30 +#define GROUP_FIELDS_CNT 31 #define GROUP_FIELDS \ " group_id," \ " group_name," \ @@ -37,6 +37,7 @@ " group_jobs_unknown," \ " group_jobs_restarted," \ " group_slots_running," \ + " stats_max_sumrss," \ " stats_max_maxrss," \ " stats_max_utime_sec," \ " stats_max_stime_sec," \ @@ -85,6 +86,7 @@ static int bind_result_group_fields(struct mx_mysql_bind *result, struct mxq_gro res += mx_mysql_bind_var(result, idx++, uint64, &(g->group_slots_running)); + res += mx_mysql_bind_var(result, idx++, uint64, &(g->stats_max_sumrss)); res += mx_mysql_bind_var(result, idx++, uint64, &(g->stats_max_maxrss)); res += mx_mysql_bind_var(result, idx++, int64, &(g->stats_max_utime.tv_sec)); res += mx_mysql_bind_var(result, idx++, int64, &(g->stats_max_stime.tv_sec)); diff --git a/mxq_group.h b/mxq_group.h index 46a352b2..7286a5a0 100644 --- a/mxq_group.h +++ b/mxq_group.h @@ -41,6 +41,7 @@ struct mxq_group { uint64_t group_slots_running; + uint64_t stats_max_sumrss; uint64_t stats_max_maxrss; struct timeval stats_max_utime; diff --git a/mxq_job.c b/mxq_job.c index f894f22b..ebde474a 100644 --- a/mxq_job.c +++ b/mxq_job.c @@ -16,7 +16,7 @@ #include "mxq_group.h" #include "mxq_job.h" -#define JOB_FIELDS_CNT 35 +#define JOB_FIELDS_CNT 36 #define JOB_FIELDS \ " job_id, " \ " job_status, " \ @@ -38,6 +38,7 @@ " 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, " \ @@ -82,6 +83,7 @@ static int bind_result_job_fields(struct mx_mysql_bind *result, struct mxq_job * res += mx_mysql_bind_var(result, idx++, int64, &(j->date_submit)); res += mx_mysql_bind_var(result, idx++, int64, &(j->date_start)); res += mx_mysql_bind_var(result, idx++, int64, &(j->date_end)); + res += mx_mysql_bind_var(result, idx++, uint64, &(j->stats_max_sumrss)); res += mx_mysql_bind_var(result, idx++, int32, &(j->stats_status)); res += mx_mysql_bind_var(result, idx++, int64, &(j->stats_rusage.ru_utime.tv_sec)); res += mx_mysql_bind_var(result, idx++, int64, &(j->stats_rusage.ru_utime.tv_usec)); @@ -474,6 +476,7 @@ int mxq_set_job_status_exited(struct mx_mysql *mysql, struct mxq_job *job) "UPDATE mxq_job SET" " job_status = ?," " date_end = NULL," + " stats_max_sumrss = ?, " " stats_status = ?, " " stats_utime_sec = ?, " " stats_utime_usec = ?, " @@ -495,12 +498,13 @@ int mxq_set_job_status_exited(struct mx_mysql *mysql, struct mxq_job *job) " AND server_id = ?" " AND host_pid = ?"; - res = mx_mysql_bind_init_param(¶m, 20); + res = mx_mysql_bind_init_param(¶m, 21); assert(res == 0); idx = 0; res = 0; res += mx_mysql_bind_var(¶m, idx++, uint16, &(newstatus)); + res += mx_mysql_bind_var(¶m, idx++, uint64, &(job->stats_max_sumrss)); res += mx_mysql_bind_var(¶m, idx++, int32, &(job->stats_status)); res += mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_utime.tv_sec)); res += mx_mysql_bind_var(¶m, idx++, int64, &(job->stats_rusage.ru_utime.tv_usec)); diff --git a/mxq_job.h b/mxq_job.h index 42b2d81d..f29baf62 100644 --- a/mxq_job.h +++ b/mxq_job.h @@ -52,6 +52,8 @@ struct mxq_job { struct timeval stats_starttime; + uint64_t stats_max_sumrss; + int32_t stats_status; struct timeval stats_realtime; struct rusage stats_rusage; diff --git a/mxqd.c b/mxqd.c index 43afc3d8..edc3ff48 100644 --- a/mxqd.c +++ b/mxqd.c @@ -1638,16 +1638,16 @@ int killall_over_memory(struct mxq_server *server) continue; } - memory = pinfo->sum_rss * pagesize / 1024 / 1024; + memory = pinfo->sum_rss * pagesize / 1024; if (job->max_sum_rss < memory) job->max_sum_rss = memory; - if (memory <= group->group.job_memory) + if (memory/1024 <= group->group.job_memory) continue; - mx_log_info("killall_over_memory(): used(%llu) > requested(%llu): Sending signal=KILL to job=%s(%d):%lu:%lu pgrp=%d", - memory, group->group.job_memory, + mx_log_info("killall_over_memory(): used(%lluMiB) > requested(%lluMiB): Sending signal=KILL to job=%s(%d):%lu:%lu pgrp=%d", + memory/1024, group->group.job_memory, group->group.user_name, group->group.user_uid, group->group.group_id, job->job.job_id, pid); kill(-pid, SIGKILL); @@ -1762,7 +1762,7 @@ int catchall(struct mxq_server *server) { g = &job->group->group; timersub(&now, &j->stats_starttime, &j->stats_realtime); - + j->stats_max_sumrss = job->max_sum_rss; j->stats_status = status; j->stats_rusage = rusage; diff --git a/mxqdump.c b/mxqdump.c index 2cac9c13..8b0b9665 100644 --- a/mxqdump.c +++ b/mxqdump.c @@ -128,6 +128,7 @@ static int print_group(struct mxq_group *g) " max_utime=%lu" " max_real=%lu" " max_memory=%lukiB" + " max_rss=%lukiB" " wait_sec=%lu" " run_sec=%lu" " idle_sec=%lu" @@ -150,10 +151,11 @@ static int print_group(struct mxq_group *g) g->job_threads, g->job_memory*1024, g->job_time*60, - (100UL*(uint64_t)g->stats_max_maxrss/1024UL/g->job_memory), + (100UL*(uint64_t)g->stats_max_sumrss/1024UL/g->job_memory), (100UL*(uint64_t)g->stats_max_real.tv_sec/60UL/g->job_time), g->stats_max_utime.tv_sec, g->stats_max_real.tv_sec, + g->stats_max_sumrss, g->stats_max_maxrss, g->stats_wait_sec, g->stats_run_sec, @@ -219,6 +221,7 @@ static int print_job(struct mxq_group *g, struct mxq_job *j) " runtime_requested=%us" " time_load=%lu%%" " memory_requested=%lukiB" + " max_memory=%lukiB" " max_rss=%lukiB" " memory_load=%lu%%" " threads=%d" @@ -244,8 +247,9 @@ static int print_job(struct mxq_group *g, struct mxq_job *j) g->job_time*60, (100UL*(run_sec)/60UL/g->job_time), g->job_memory*1024, + j->stats_max_sumrss, j->stats_rusage.ru_maxrss, - (100UL*j->stats_rusage.ru_maxrss/1024UL/g->job_memory), + (100UL*j->stats_max_sumrss/1024UL/g->job_memory), g->job_threads, j->host_slots, mxq_job_status_to_name(j->job_status), diff --git a/mysql/alter_tables_0.17.0.sql b/mysql/alter_tables_0.17.0.sql new file mode 100644 index 00000000..b9daa722 --- /dev/null +++ b/mysql/alter_tables_0.17.0.sql @@ -0,0 +1,11 @@ +ALTER TABLE mxq_group + ADD COLUMN + stats_max_sumrss INT8 UNSIGNED NOT NULL DEFAULT 0 + AFTER + group_date_end; + +ALTER TABLE mxq_job + ADD COLUMN + stats_max_sumrss INT8 UNSIGNED NOT NULL DEFAULT 0 + AFTER + job_id_first; diff --git a/mysql/create_tables.sql b/mysql/create_tables.sql index 978c679f..f2566cc6 100644 --- a/mysql/create_tables.sql +++ b/mysql/create_tables.sql @@ -34,6 +34,8 @@ CREATE TABLE IF NOT EXISTS mxq_group ( group_date_end TIMESTAMP NOT NULL DEFAULT 0, + stats_max_sumrss INT8 UNSIGNED NOT NULL DEFAULT 0, + stats_max_maxrss INT8 UNSIGNED NOT NULL DEFAULT 0, stats_max_utime_sec INT8 UNSIGNED NOT NULL DEFAULT 0, stats_max_stime_sec INT8 UNSIGNED NOT NULL DEFAULT 0, @@ -94,6 +96,8 @@ CREATE TABLE IF NOT EXISTS mxq_job ( job_id_old INT8 UNSIGNED NULL DEFAULT NULL, job_id_first INT8 UNSIGNED NULL DEFAULT NULL, + stats_max_sumrss INT8 UNSIGNED NOT NULL DEFAULT 0, + stats_status INT4 UNSIGNED NOT NULL DEFAULT 0, stats_utime_sec INT8 UNSIGNED NOT NULL DEFAULT 0, diff --git a/mysql/create_trigger.sql b/mysql/create_trigger.sql index ccd2af6e..c4269acf 100644 --- a/mysql/create_trigger.sql +++ b/mysql/create_trigger.sql @@ -64,6 +64,7 @@ CREATE TRIGGER mxq_update_job BEFORE UPDATE ON mxq_job group_slots_running=group_slots_running-NEW.host_slots, group_jobs_running=group_jobs_running-1, group_jobs_failed=group_jobs_failed+1, + stats_max_sumrss=GREATEST(stats_max_sumrss, NEW.stats_max_sumrss), stats_max_maxrss=GREATEST(stats_max_maxrss, NEW.stats_maxrss), stats_max_utime_sec=GREATEST(stats_max_utime_sec, NEW.stats_utime_sec), stats_max_stime_sec=GREATEST(stats_max_stime_sec, NEW.stats_stime_sec), @@ -99,6 +100,7 @@ CREATE TRIGGER mxq_update_job BEFORE UPDATE ON mxq_job group_slots_running=group_slots_running-NEW.host_slots, group_jobs_running=group_jobs_running-1, group_jobs_finished=group_jobs_finished+1, + stats_max_sumrss=GREATEST(stats_max_sumrss, NEW.stats_max_sumrss), stats_max_maxrss=GREATEST(stats_max_maxrss, NEW.stats_maxrss), stats_max_utime_sec=GREATEST(stats_max_utime_sec, NEW.stats_utime_sec), stats_max_stime_sec=GREATEST(stats_max_stime_sec, NEW.stats_stime_sec), @@ -113,6 +115,7 @@ CREATE TRIGGER mxq_update_job BEFORE UPDATE ON mxq_job WHERE group_id=NEW.group_id; ELSEIF NEW.job_status NOT IN (399, 755, 989, 990) THEN UPDATE mxq_group SET + stats_max_sumrss=GREATEST(stats_max_sumrss, NEW.stats_max_sumrss), stats_max_maxrss=GREATEST(stats_max_maxrss, NEW.stats_maxrss), stats_max_utime_sec=GREATEST(stats_max_utime_sec, NEW.stats_utime_sec), stats_max_stime_sec=GREATEST(stats_max_stime_sec, NEW.stats_stime_sec), diff --git a/web/pages/mxq/mxq.in b/web/pages/mxq/mxq.in index 6a4f8b2b..db24812d 100755 --- a/web/pages/mxq/mxq.in +++ b/web/pages/mxq/mxq.in @@ -269,6 +269,7 @@ group_mtime : $o{group_mtime} group_date_end : $o{group_date_end} +stats_max_sumrss : $o{stats_max_maxrss} kiB stats_max_maxrss : $o{stats_max_maxrss} stats_max_utime_sec : $o{stats_max_utime_sec} stats_max_stime_sec : $o{stats_max_stime_sec} @@ -364,6 +365,8 @@ job_id_new : $o{job_id_new} job_id_old : $o{job_id_old} job_id_first : $o{job_id_first} +stats_max_sumrss : $o{stats_max_maxrss} kiB + stats_status : $o{stats_status} stats_utime_sec : $o{stats_utime_sec} From df2c998bd5e751d08364f47146a7b2c79860f955 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 26 Oct 2015 14:15:44 +0100 Subject: [PATCH 26/34] mxqd: Send TERM to process when over memory instead of KILL to pgrp --- mxqd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mxqd.c b/mxqd.c index edc3ff48..bec2797b 100644 --- a/mxqd.c +++ b/mxqd.c @@ -1646,11 +1646,11 @@ int killall_over_memory(struct mxq_server *server) if (memory/1024 <= group->group.job_memory) continue; - mx_log_info("killall_over_memory(): used(%lluMiB) > requested(%lluMiB): Sending signal=KILL to job=%s(%d):%lu:%lu pgrp=%d", + mx_log_info("killall_over_memory(): used(%lluMiB) > requested(%lluMiB): Sending signal=TERM to job=%s(%d):%lu:%lu pid=%d", memory/1024, group->group.job_memory, group->group.user_name, group->group.user_uid, group->group.group_id, job->job.job_id, pid); - kill(-pid, SIGKILL); + kill(pid, SIGTERM); } } } From 9f5688d51bd95ea3f3892819d0f92ef2ff7c3026 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 26 Oct 2015 14:22:04 +0100 Subject: [PATCH 27/34] MXQ bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b6b0e805..fe158d5a 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ MXQ_VERSION_MAJOR = 0 -MXQ_VERSION_MINOR = 17 +MXQ_VERSION_MINOR = 18 MXQ_VERSION_PATCH = 0 MXQ_VERSION_EXTRA = "beta" MXQ_VERSIONDATE = 2015 From 516c0f644596e2fa9486414946787bd169b02b14 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 26 Oct 2015 14:27:19 +0100 Subject: [PATCH 28/34] mxqd: Fix root check --- mxqd.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/mxqd.c b/mxqd.c index bec2797b..697eff50 100644 --- a/mxqd.c +++ b/mxqd.c @@ -433,6 +433,15 @@ int server_init(struct mxq_server *server, int argc, char *argv[]) MX_GETOPT_FINISH(optctl, argc, argv); + if (!RUNNING_AS_ROOT) { +#if defined(MXQ_DEVELOPMENT) || defined(RUNASNORMALUSER) + mx_log_notice("Running mxqd as non-root user."); +#else + mx_log_err("Running mxqd as non-root user is not supported at the moment."); + exit(EX_USAGE); +#endif + } + if (arg_daemonize && arg_nolog) { mx_log_err("Error while using conflicting options --daemonize and --no-log at once."); exit(EX_USAGE); @@ -501,15 +510,6 @@ int server_init(struct mxq_server *server, int argc, char *argv[]) } } - if (!RUNNING_AS_ROOT) { -#if defined(MXQ_DEVELOPMENT) || defined(RUNASNORMALUSER) - mx_log_notice("Running mxqd as non-root user."); -#else - mx_log_err("Running mxqd as non-root user is not supported at the moment."); - exit(EX_USAGE); -#endif - } - res = mx_read_first_line_from_file("/proc/sys/kernel/random/boot_id", &str_bootid); assert(res == 36); assert(str_bootid); From 498c7a7c71251fb681b3d62734a6877050330a5f Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 26 Oct 2015 14:28:52 +0100 Subject: [PATCH 29/34] MXQ bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index fe158d5a..fa1f1ae7 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ MXQ_VERSION_MAJOR = 0 MXQ_VERSION_MINOR = 18 -MXQ_VERSION_PATCH = 0 +MXQ_VERSION_PATCH = 1 MXQ_VERSION_EXTRA = "beta" MXQ_VERSIONDATE = 2015 From 6f9e118cd7ca5a628cf24d11c335b81d63598f8a Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Mon, 26 Oct 2015 14:28:05 +0100 Subject: [PATCH 30/34] mxqd: fix typo in log --- mxqd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mxqd.c b/mxqd.c index 697eff50..167ed126 100644 --- a/mxqd.c +++ b/mxqd.c @@ -1143,7 +1143,7 @@ unsigned long start_job(struct mxq_group_list *group) group->group.user_name, group->group.user_uid, group->group.group_id, mxqjob.job_id); cpuset_init_job(&mxqjob.host_cpu_set,&server->cpu_set_available,&server->cpu_set_running,group->slots_per_job); - cpuset_log(" job assgined cpus: ",&mxqjob.host_cpu_set); + cpuset_log(" job assigned cpus: ",&mxqjob.host_cpu_set); mx_mysql_disconnect(server->mysql); From a092d65b2265c29cd4dd15fbff2fe8a9ad00ce57 Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Thu, 22 Oct 2015 18:38:41 +0200 Subject: [PATCH 31/34] mxq_job: fix memory leak --- mxq_job.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mxq_job.c b/mxq_job.c index ebde474a..d4bbe21f 100644 --- a/mxq_job.c +++ b/mxq_job.c @@ -670,6 +670,7 @@ int mxq_load_job_from_group_for_server(struct mx_mysql *mysql, struct mxq_job *m } if(res == 1) { memcpy(mxqjob, &jobs[0], sizeof(*mxqjob)); + free(jobs); break; } From c8a578414f517f628d048454a7bea069c420f1e5 Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Thu, 22 Oct 2015 13:34:26 +0200 Subject: [PATCH 32/34] web: show threads in group table and runtime in minutes for completed jobs --- web/pages/mxq/mxq.in | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/web/pages/mxq/mxq.in b/web/pages/mxq/mxq.in index db24812d..e938bbec 100755 --- a/web/pages/mxq/mxq.in +++ b/web/pages/mxq/mxq.in @@ -312,7 +312,7 @@ sub job { $dbh or db_init(); - my $sth=$dbh->prepare('SELECT *,timestampdiff(MINUTE,date_start,now()) as t FROM mxq_job WHERE job_id=? LIMIT 1',undef); + my $sth=$dbh->prepare('SELECT *,timestampdiff(MINUTE,date_start,now()) as t,timestampdiff(MINUTE,date_start,date_end) as t2 FROM mxq_job WHERE job_id=? LIMIT 1',undef); $sth->execute($job_id); my %o=%{$sth->fetchrow_hashref('NAME_lc')}; @@ -326,8 +326,8 @@ sub job { my $job_stdout=escapeHTML($o{job_stdout}); my $job_stderr=escapeHTML($o{job_stderr}); - - my $ago = defined $o{t} ? "($o{t} minutes ago)" : ''; + my $ago = $job_status_text eq 'RUNNING' && defined $o{t} ? "($o{t} minutes ago)" : ''; + my $rt = defined $o{t2} ? "($o{t2} minutes runtime)" : ''; defined $_ or $_='<null>' for values %o; @@ -359,7 +359,7 @@ host_slots : $o{host_slots} date_submit : $o{date_submit} date_start : $o{date_start} $ago -date_end : $o{date_end} +date_end : $o{date_end} $rt job_id_new : $o{job_id_new} job_id_old : $o{job_id_old} @@ -397,17 +397,17 @@ sub group_table_rows { $out.=$q->Tr($q->th($head)); while (my $row=$sth->fetchrow_arrayref()) { - my ($group_id,$group_name,$user_name,$group_mtime,$group_status, + my ($group_id,$group_name,$job_threads,$user_name,$group_mtime,$group_status, $group_jobs,$group_jobs_inq,$group_jobs_running,$group_jobs_finished,$group_jobs_failed,$group_jobs_cancelled,$group_jobs_unknown )=@$row; $out.=$q->Tr( $q->td({class=>'number'},$q->a({href=>selfurl("/group/$group_id")},$group_id)), $q->td($group_name), + $q->td({class=>'number'},$job_threads), $q->td($user_name), $q->td($group_mtime), $q->td(group_status($group_status)), - $q->td({class=>'number'},$group_jobs), $q->td({class=>'number'},$group_jobs_inq), $q->td({class=>'number'},$group_jobs_running), @@ -429,11 +429,11 @@ sub group_table { my $out; my @cols=qw( - group_id group_name user_name group_mtime group_status + group_id group_name job_threads user_name group_mtime group_status group_jobs group_jobs_inq group_jobs_running group_jobs_finished group_jobs_failed group_jobs_cancelled group_jobs_unknown ); my @head=qw( - group_id group_name user_name group_mtime group_status + group_id group_name threads user_name group_mtime group_status jobs inq running finished failed cancelled unknown ); @@ -447,6 +447,7 @@ sub group_table { @cols=qw( group_id group_name + job_threads user_name group_date_end group_status @@ -460,6 +461,7 @@ sub group_table { @head=qw( group_id group_name + threads user_name date_end group_status From 0e1b70d0bcbb0402208bd4c26015d262427ad847 Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Mon, 26 Oct 2015 15:55:26 +0100 Subject: [PATCH 33/34] make: add LOCALSTATEDIR --- Makefile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Makefile b/Makefile index fa1f1ae7..deeda390 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,7 @@ LIBEXECDIR = ${EPREFIX}/libexec DATADIR = ${PREFIX}/share MANDIR = ${DATADIR}/man SYSCONFDIR = ${PREFIX}/etc +LOCALSTATEDIR = ${PREFIX}/var DESTDIR= @@ -43,6 +44,11 @@ ifneq (, $(filter /usr /usr/local, ${PREFIX})) SYSCONFDIR = /etc endif +### set localstatedir /var if prefix /usr || /usr/local +ifneq (, $(filter /usr /usr/local, ${PREFIX})) + LOCALSTATEDIR = /var +endif + ######################################################################## ### strip /mxq from SYSCONFDIR if set @@ -125,6 +131,7 @@ CFLAGS += -DLIBEXECDIR=\"${LIBEXECDIR}\" CFLAGS += -DDATADIR=\"${DATADIR}\" CFLAGS += -DMANDIR=\"${MANDIR}\" CFLAGS += -DSYSCONFDIR=\"${SYSCONFDIR}\" +CFLAGS += -DLOCALSTATEDIR=\"${LOCALSTATEDIR}\" CFLAGS += $(EXTRA_CFLAGS) ######################################################################## From 2d2bb58d8c325aed8d0d8b3060810ce6f588715b Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Tue, 27 Oct 2015 10:40:23 +0100 Subject: [PATCH 34/34] MXQ bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index deeda390..1d1bd5a2 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ MXQ_VERSION_MAJOR = 0 MXQ_VERSION_MINOR = 18 -MXQ_VERSION_PATCH = 1 +MXQ_VERSION_PATCH = 2 MXQ_VERSION_EXTRA = "beta" MXQ_VERSIONDATE = 2015