Skip to content

Commit 02e0b83

Browse files
committed
state match
1 parent 44a0180 commit 02e0b83

File tree

2 files changed

+112
-4
lines changed

2 files changed

+112
-4
lines changed

src/modules/job-list/match.c

Lines changed: 100 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "match.h"
2424

2525
typedef bool (*match_f) (struct constraint *, const struct job *);
26+
typedef struct constraint * (*create_f) (json_t *, flux_error_t *);
2627
typedef int (*array_to_bitmask_f) (json_t *, flux_error_t *);
2728

2829
struct constraint {
@@ -84,6 +85,9 @@ static bool match_not (struct constraint *c, const struct job *job)
8485
}
8586

8687
static struct constraint *conditional_constraint (const char *type,
88+
match_f match_or_cb,
89+
match_f match_not_cb,
90+
create_f create_cb,
8791
json_t *values,
8892
flux_error_t *errp)
8993
{
@@ -101,13 +105,13 @@ static struct constraint *conditional_constraint (const char *type,
101105
if (streq (type, "and"))
102106
c->match = match_and;
103107
else if (streq (type, "or"))
104-
c->match = match_or;
108+
c->match = match_or_cb;
105109
else if (streq (type, "not"))
106-
c->match = match_not;
110+
c->match = match_not_cb;
107111
zlistx_set_destructor (c->values, constraint_destructor);
108112

109113
json_array_foreach (values, index, entry) {
110-
struct constraint *cp = constraint_create (entry, errp);
114+
struct constraint *cp = create_cb (entry, errp);
111115
if (!cp)
112116
goto error;
113117
if (!zlistx_add_end (c->values, cp)) {
@@ -452,7 +456,12 @@ struct constraint *constraint_create (json_t *constraint, flux_error_t *errp)
452456
else if (streq (op, "since"))
453457
return create_since_constraint (values, errp);
454458
else if (streq (op, "or") || streq (op, "and") || streq (op, "not"))
455-
return conditional_constraint (op, values, errp);
459+
return conditional_constraint (op,
460+
match_or,
461+
match_not,
462+
constraint_create,
463+
values,
464+
errp);
456465
else {
457466
errprintf (errp, "unknown constraint operator: %s", op);
458467
return NULL;
@@ -468,5 +477,92 @@ bool job_match (const struct job *job, struct constraint *constraint)
468477
return constraint->match (constraint, job);
469478
}
470479

480+
static bool match_or_checkempty (struct constraint *c, const struct job *job)
481+
{
482+
struct constraint *cp = zlistx_first (c->values);
483+
bool ran_a_match = false;
484+
while (cp) {
485+
if (cp->match (cp, job))
486+
return true;
487+
ran_a_match = true;
488+
cp = zlistx_next (c->values);
489+
}
490+
/* corner case: if no ops, assume this is true */
491+
if (!ran_a_match)
492+
return true;
493+
return false;
494+
}
495+
496+
static bool match_not_checkempty (struct constraint *c, const struct job *job)
497+
{
498+
struct constraint *cp = zlistx_first (c->values);
499+
bool ran_a_match = false;
500+
while (cp) {
501+
if (!cp->match (cp, job))
502+
return true;
503+
if (cp->match != match_empty)
504+
ran_a_match = true;
505+
cp = zlistx_next (c->values);
506+
}
507+
/* if no real match callbacks were run, assume this conditional is true */
508+
if (!ran_a_match)
509+
return true;
510+
return false;
511+
}
512+
513+
struct constraint *state_constraint_create (json_t *constraint,
514+
flux_error_t *errp)
515+
{
516+
const char *op;
517+
json_t *values;
518+
519+
if (!constraint || !json_is_object (constraint)) {
520+
errprintf (errp, "constraint must be JSON object");
521+
return NULL;
522+
}
523+
if (json_object_size (constraint) > 1) {
524+
errprintf (errp, "constraint must only contain 1 element");
525+
return NULL;
526+
}
527+
json_object_foreach (constraint, op, values) {
528+
if (!json_is_array (values)) {
529+
errprintf (errp, "operator %s values not an array", op);
530+
return NULL;
531+
}
532+
if (streq (op, "userid")
533+
|| streq (op, "name")
534+
|| streq (op, "queue")
535+
|| streq (op, "results")
536+
|| streq (op, "since"))
537+
return constraint_new (errp);
538+
else if (streq (op, "states"))
539+
return create_states_constraint (values, errp);
540+
else if (streq (op, "or") || streq (op, "and") || streq (op, "not"))
541+
return conditional_constraint (op,
542+
match_or_checkempty,
543+
match_not_checkempty,
544+
state_constraint_create,
545+
values,
546+
errp);
547+
else {
548+
errprintf (errp, "unknown constraint operator: %s", op);
549+
return NULL;
550+
}
551+
}
552+
return constraint_new (errp);
553+
}
554+
555+
bool state_match (flux_job_state_t state, struct constraint *constraint)
556+
{
557+
int valid_states = (FLUX_JOB_STATE_ACTIVE | FLUX_JOB_STATE_INACTIVE);
558+
struct job job;
559+
560+
if (!state || (state & ~valid_states) || !constraint)
561+
return false;
562+
563+
job.state = state;
564+
return constraint->match (constraint, &job);
565+
}
566+
471567
/* vi: ts=4 sw=4 expandtab
472568
*/

src/modules/job-list/match.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,16 @@ void constraint_destroy (struct constraint *constraint);
3434
*/
3535
bool job_match (const struct job *job, struct constraint *constraint);
3636

37+
/* Identical to constraint_create() but only cares about
38+
* "states" operation. Effectively tests the "states" constraint
39+
* operation and everything else is considered true all of the time.
40+
*/
41+
struct constraint *state_constraint_create (json_t *constraint,
42+
flux_error_t *errp);
43+
44+
/* determines if a job in 'state' could potentially return true with
45+
* the given constraint.
46+
*/
47+
bool state_match (flux_job_state_t state, struct constraint *constraint);
48+
3749
#endif /* !HAVE_JOB_LIST_MATCH_H */

0 commit comments

Comments
 (0)