1
/*****************************************************************************\
2
* builtin.h - header for simple builtin scheduler plugin.
3
* Periodically when pending jobs can start.
4
* This is a minimal implementation of the logic found in
5
* src/plugins/sched/backfill/backfill.c and disregards
6
* how jobs are scheduled sequencially.
7
*****************************************************************************
8
* Copyright (C) 2003-2007 The Regents of the University of California.
9
* Copyright (C) 2008-2010 Lawrence Livermore National Security.
10
* Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
11
* Written by Morris Jette <jette1@llnl.gov>
12
* CODE-OCEC-09-009. All rights reserved.
14
* This file is part of SLURM, a resource management program.
15
* For details, see <https://computing.llnl.gov/linux/slurm/>.
16
* Please also read the included file: DISCLAIMER.
18
* SLURM is free software; you can redistribute it and/or modify it under
19
* the terms of the GNU General Public License as published by the Free
20
* Software Foundation; either version 2 of the License, or (at your option)
23
* In addition, as a special exception, the copyright holders give permission
24
* to link the code of portions of this program with the OpenSSL library under
25
* certain conditions as described in each individual source file, and
26
* distribute linked combinations including the two. You must obey the GNU
27
* General Public License in all respects for all of the code used other than
28
* OpenSSL. If you modify file(s) with this exception, you may extend this
29
* exception to your version of the file(s), but you are not obligated to do
30
* so. If you do not wish to do so, delete this exception statement from your
31
* version. If you delete this exception statement from all source files in
32
* the program, then also delete it here.
34
* SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
35
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
36
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
39
* You should have received a copy of the GNU General Public License along
40
* with SLURM; if not, write to the Free Software Foundation, Inc.,
41
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
42
\*****************************************************************************/
51
#include "slurm/slurm.h"
52
#include "slurm/slurm_errno.h"
54
#include "src/common/list.h"
55
#include "src/common/macros.h"
56
#include "src/common/node_select.h"
57
#include "src/common/parse_time.h"
58
#include "src/common/slurm_protocol_api.h"
59
#include "src/common/xmalloc.h"
60
#include "src/common/xstring.h"
62
#include "src/slurmctld/locks.h"
63
#include "src/slurmctld/preempt.h"
64
#include "src/slurmctld/reservation.h"
65
#include "src/slurmctld/slurmctld.h"
66
#include "src/plugins/sched/builtin/builtin.h"
68
#ifndef BACKFILL_INTERVAL
69
# define BACKFILL_INTERVAL 30
72
/*********************** local variables *********************/
73
static bool stop_builtin = false;
74
static pthread_mutex_t term_lock = PTHREAD_MUTEX_INITIALIZER;
75
static pthread_cond_t term_cond = PTHREAD_COND_INITIALIZER;
76
static bool config_flag = false;
77
static int backfill_interval = BACKFILL_INTERVAL;
78
static int max_backfill_job_cnt = 50;
79
static int sched_timeout = 0;
81
/*********************** local functions *********************/
82
static void _compute_start_times(void);
83
static void _load_config(void);
84
static void _my_sleep(int secs);
86
/* Terminate builtin_agent */
87
extern void stop_builtin_agent(void)
89
pthread_mutex_lock(&term_lock);
91
pthread_cond_signal(&term_cond);
92
pthread_mutex_unlock(&term_lock);
95
static void _my_sleep(int secs)
97
struct timespec ts = {0, 0};
99
ts.tv_sec = time(NULL) + secs;
100
pthread_mutex_lock(&term_lock);
102
pthread_cond_timedwait(&term_cond, &term_lock, &ts);
103
pthread_mutex_unlock(&term_lock);
106
static void _load_config(void)
108
char *sched_params, *tmp_ptr;
110
sched_timeout = slurm_get_msg_timeout() / 2;
111
sched_timeout = MAX(sched_timeout, 1);
112
sched_timeout = MIN(sched_timeout, 10);
114
sched_params = slurm_get_sched_params();
116
if (sched_params && (tmp_ptr=strstr(sched_params, "interval=")))
117
backfill_interval = atoi(tmp_ptr + 9);
118
if (backfill_interval < 1) {
119
fatal("Invalid backfill scheduler interval: %d",
123
if (sched_params && (tmp_ptr=strstr(sched_params, "max_job_bf=")))
124
max_backfill_job_cnt = atoi(tmp_ptr + 11);
125
if (max_backfill_job_cnt < 1) {
126
fatal("Invalid backfill scheduler max_job_bf: %d",
127
max_backfill_job_cnt);
132
static void _compute_start_times(void)
134
int j, rc = SLURM_SUCCESS, job_cnt = 0;
136
job_queue_rec_t *job_queue_rec;
137
List preemptee_candidates = NULL;
138
struct job_record *job_ptr;
139
struct part_record *part_ptr;
140
bitstr_t *alloc_bitmap = NULL, *avail_bitmap = NULL;
141
uint32_t max_nodes, min_nodes, req_nodes, time_limit;
142
time_t now = time(NULL), sched_start, last_job_alloc;
145
last_job_alloc = now - 1;
146
alloc_bitmap = bit_alloc(node_record_count);
147
if (alloc_bitmap == NULL)
148
fatal("bit_alloc: malloc failure");
149
job_queue = build_job_queue(true);
150
while ((job_queue_rec = (job_queue_rec_t *)
151
list_pop_bottom(job_queue, sort_job_queue2))) {
152
job_ptr = job_queue_rec->job_ptr;
153
part_ptr = job_queue_rec->part_ptr;
154
xfree(job_queue_rec);
155
if (part_ptr != job_ptr->part_ptr)
156
continue; /* Only test one partition */
158
if (job_cnt++ > max_backfill_job_cnt) {
159
debug("backfill: loop taking to long, breaking out");
163
/* Determine minimum and maximum node counts */
164
min_nodes = MAX(job_ptr->details->min_nodes,
165
part_ptr->min_nodes);
167
if (job_ptr->details->max_nodes == 0)
168
max_nodes = part_ptr->max_nodes;
170
max_nodes = MIN(job_ptr->details->max_nodes,
171
part_ptr->max_nodes);
173
max_nodes = MIN(max_nodes, 500000); /* prevent overflows */
175
if (job_ptr->details->max_nodes)
176
req_nodes = max_nodes;
178
req_nodes = min_nodes;
180
if (min_nodes > max_nodes) {
181
/* job's min_nodes exceeds partition's max_nodes */
185
j = job_test_resv(job_ptr, &now, true, &avail_bitmap);
186
if (j != SLURM_SUCCESS)
189
rc = select_g_job_test(job_ptr, avail_bitmap,
190
min_nodes, max_nodes, req_nodes,
191
SELECT_MODE_WILL_RUN,
192
preemptee_candidates, NULL);
193
last_job_update = now;
195
if (job_ptr->time_limit == INFINITE)
196
time_limit = 365 * 24 * 60 * 60;
197
else if (job_ptr->time_limit != NO_VAL)
198
time_limit = job_ptr->time_limit * 60;
199
else if (job_ptr->part_ptr &&
200
(job_ptr->part_ptr->max_time != INFINITE))
201
time_limit = job_ptr->part_ptr->max_time * 60;
203
time_limit = 365 * 24 * 60 * 60;
204
if (bit_overlap(alloc_bitmap, avail_bitmap) &&
205
(job_ptr->start_time <= last_job_alloc)) {
206
job_ptr->start_time = last_job_alloc;
208
bit_or(alloc_bitmap, avail_bitmap);
209
last_job_alloc = job_ptr->start_time + time_limit;
210
FREE_NULL_BITMAP(avail_bitmap);
212
if ((time(NULL) - sched_start) >= sched_timeout) {
213
debug("backfill: loop taking to long, breaking out");
217
list_destroy(job_queue);
218
FREE_NULL_BITMAP(alloc_bitmap);
221
/* Note that slurm.conf has changed */
222
extern void builtin_reconfig(void)
227
/* builtin_agent - detached thread periodically when pending jobs can start */
228
extern void *builtin_agent(void *args)
232
static time_t last_backfill_time = 0;
233
/* Read config, nodes and partitions; Write jobs */
234
slurmctld_lock_t all_locks = {
235
READ_LOCK, WRITE_LOCK, READ_LOCK, READ_LOCK };
238
last_backfill_time = time(NULL);
239
while (!stop_builtin) {
240
_my_sleep(backfill_interval);
248
wait_time = difftime(now, last_backfill_time);
249
if ((wait_time < backfill_interval))
252
lock_slurmctld(all_locks);
253
_compute_start_times();
254
last_backfill_time = time(NULL);
255
unlock_slurmctld(all_locks);