// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 package nomad import "github.com/hashicorp/nomad/nomad/structs" // systemEvals are handled specially, each job may have a blocked eval on each node type systemEvals struct { // byJob maps a jobID to a nodeID to that job's single blocked evalID on that node byJob map[structs.NamespacedID]map[string]string // byNode maps a nodeID to a set of evalIDs byNode map[string]map[string]bool // evals maps evalIDs to an eval and token evals map[string]*wrappedEval } func newSystemEvals() *systemEvals { return &systemEvals{ evals: map[string]*wrappedEval{}, byJob: map[structs.NamespacedID]map[string]string{}, byNode: map[string]map[string]bool{}, } } func (s *systemEvals) Add(eval *structs.Evaluation, token string) { // store the eval by node id if _, ok := s.byNode[eval.NodeID]; !ok { s.byNode[eval.NodeID] = make(map[string]bool) } s.byNode[eval.NodeID][eval.ID] = true s.evals[eval.ID] = &wrappedEval{eval: eval, token: token} // link the job to the node for cleanup jobID := structs.NewNamespacedID(eval.JobID, eval.Namespace) if _, ok := s.byJob[jobID]; !ok { s.byJob[jobID] = make(map[string]string) } // if we're displacing the old blocked id for this job+node, delete it first if prevID, ok := s.byJob[jobID][eval.NodeID]; ok { prev, _ := s.Get(prevID) s.Remove(prev.eval) } // set this eval as the new eval for this job on this node s.byJob[jobID][eval.NodeID] = eval.ID } func (s *systemEvals) Get(evalID string) (*wrappedEval, bool) { w, ok := s.evals[evalID] return w, ok } func (s *systemEvals) Remove(eval *structs.Evaluation) { // delete the job index if this eval is the currently listed blocked eval jobID := structs.NewNamespacedID(eval.JobID, eval.Namespace) e, ok := s.byJob[jobID][eval.NodeID] if ok && e == eval.ID { delete(s.byJob[jobID], eval.NodeID) } // delete this eval from the node index, and then the map for this node if empty delete(s.byNode[eval.NodeID], eval.ID) if len(s.byNode[eval.NodeID]) == 0 { delete(s.byNode, eval.NodeID) } // delete the eval itself delete(s.evals, eval.ID) } func (s *systemEvals) NodeEvals(nodeID string) (map[*structs.Evaluation]string, bool) { out := map[*structs.Evaluation]string{} for eID := range s.byNode[nodeID] { if w, ok := s.Get(eID); ok { out[w.eval] = w.token } } ok := len(out) > 0 return out, ok } func (s *systemEvals) JobEvals(jobID structs.NamespacedID) ([]*structs.Evaluation, bool) { out := []*structs.Evaluation{} _, ok := s.byJob[jobID] for _, eID := range s.byJob[jobID] { if e, ok := s.Get(eID); ok { out = append(out, e.eval) } } return out, ok }