2323#include "match.h"
2424
2525typedef bool (* match_f ) (struct constraint * , const struct job * );
26+ typedef struct constraint * (* create_f ) (json_t * , flux_error_t * );
2627typedef int (* array_to_bitmask_f ) (json_t * , flux_error_t * );
2728
2829struct constraint {
@@ -84,6 +85,9 @@ static bool match_not (struct constraint *c, const struct job *job)
8485}
8586
8687static 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 */
0 commit comments