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;