From b80317484adef66f671f37bcaa9762eabe79e99f Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Thu, 15 Aug 2024 10:55:43 +0200 Subject: [PATCH] mxqkill: Add function `cancel_group` and refactor group cancellation logic Refactor the group cancellation process by moving the code from main() into new functions, similar to the existing jobs cancellation functions. Added `cancel_group` function along with its helper functions. Notable change: - Removed constraints from the old code, making it no longer mandatory for the group to have `groups_status OK`, or pending/running jobs. This allows cancellations of both inactive and previously cancelled groups. These changes enable more flexible group management and simplify the cancellation logic. Note: The old code will be removed in the next commit for cleaner diffs and improved clarity. --- mxqkill.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/mxqkill.c b/mxqkill.c index 05890a3..1dc48d5 100644 --- a/mxqkill.c +++ b/mxqkill.c @@ -207,6 +207,86 @@ static void cancel_job(struct mx_mysql *mysql, uint64_t job_id, uint64_t user_ui set_job_cancelled(mysql, job_id); } +static void verify_group_owner(struct mx_mysql *mysql, uint64_t group_id, uint64_t user_uid) { + struct mx_mysql_stmt *stmt = mx_mysql_statement_prepare(mysql, + "SELECT user_uid FROM mxq_group" + " WHERE group_id = ?" + ); + if (!stmt) + mx_die("mx_mysql_statement_prepare(): %s\n", mx_mysql_error()); + + mx_mysql_statement_param_bind(stmt, 0, uint64, &group_id); + + unsigned long long num_rows; + int res = mx_mysql_statement_execute(stmt, &num_rows); + if (res < 0) + mx_die("mx_mysql_statement_execute(): %s\n", mx_mysql_error()); + + if (num_rows == 0) + mx_die("no such group_id %lu\n", group_id); + + uint64_t uid; + mx_mysql_statement_result_bind(stmt, 0, uint64, &uid); + + res = mx_mysql_statement_fetch(stmt); + if (res < 0) + mx_die("mx_mysql_statement_fetch: %s\n", mx_mysql_error()); + + if (uid != user_uid) + mx_die("group %lu: permission denied\n", group_id); + + mx_mysql_statement_close(&stmt); +} + +static void set_group_cancelled(struct mx_mysql *mysql, uint64_t group_id) { + struct mx_mysql_stmt *stmt = mx_mysql_statement_prepare(mysql, + "UPDATE mxq_group SET group_status = " status_str(MXQ_GROUP_STATUS_CANCELLED) + " WHERE group_id = ?" + ); + if (!stmt) + mx_die("mx_mysql_statement_prepare(): %s\n", mx_mysql_error()); + + mx_mysql_statement_param_bind(stmt, 0, uint64, &group_id); + + unsigned long long num_rows; + int res = mx_mysql_statement_execute(stmt, &num_rows); + if (res < 0) + mx_die("mx_mysql_statement_execute(): %s\n", mx_mysql_error()); + if (num_rows == 0) + mx_die("no such group_id %lu\n", group_id); + + mx_mysql_statement_close(&stmt); +} + +static void cancel_pending_jobs(struct mx_mysql *mysql, uint64_t group_id) { + struct mx_mysql_stmt *stmt = mx_mysql_statement_prepare(mysql, + "UPDATE mxq_job SET job_cancelled = TRUE" + " WHERE group_id = ?" + " AND job_status = " status_str(MXQ_JOB_STATUS_INQ) + ); + if (!stmt) + mx_die("mx_mysql_statement_prepare(): %s\n", mx_mysql_error()); + + mx_mysql_statement_param_bind(stmt, 0, uint64, &group_id); + + unsigned long long num_rows; + int res = mx_mysql_statement_execute(stmt, &num_rows); + if (res < 0) + mx_die("mx_mysql_statement_execute(): %s\n", mx_mysql_error()); + if (num_rows) + mx_log_notice("cancelled %llu jobs in group with group_id=%lu", num_rows, group_id); + mx_mysql_statement_close(&stmt); +} + +void cancel_group(struct mx_mysql *mysql, uint64_t group_id, uint64_t user_uid) { + + verify_group_owner(mysql, group_id, user_uid); + set_group_cancelled(mysql, group_id); + cancel_pending_jobs(mysql, group_id); + mx_log_notice("marked all running jobs in group with group_id=%lu to be killed by executing servers.", group_id); + mx_log_notice("deactivated group with group_id=%lu", group_id); +} + int main(int argc, char *argv[]) { struct mx_mysql *mysql = NULL;