<commit_before>package scheduler

import "github.com/docker/swarm-v2/api"

// NodeInfo contains a node and some additional metadata.
type NodeInfo struct {
	*api.Node
	Tasks              map[string]*api.Task
	AvailableResources api.Resources

	// There are some corner cases where we may assign multiple tasks that
	// need the same port to a single node. To deal with this properly,
	// ReservedPorts has a set of tasks using each port rather than just a
	// set of ports.
	ReservedPorts map[uint32]map[string]struct{}
}

func newNodeInfo(n *api.Node, tasks map[string]*api.Task, availableResources api.Resources) NodeInfo {
	nodeInfo := NodeInfo{
		Node:               n,
		Tasks:              make(map[string]*api.Task),
		AvailableResources: availableResources,
		ReservedPorts:      make(map[uint32]map[string]struct{}),
	}

	for _, t := range tasks {
		nodeInfo.addTask(t)
	}
	return nodeInfo
}

func (nodeInfo *NodeInfo) removeTask(t *api.Task) bool {
	if nodeInfo.Tasks != nil {
		if _, ok := nodeInfo.Tasks[t.ID]; ok {
			delete(nodeInfo.Tasks, t.ID)
			if t.GetContainer() != nil {
				specContainer := t.GetContainer().Spec
				reservations := taskReservations(&specContainer)
				nodeInfo.AvailableResources.MemoryBytes += reservations.MemoryBytes
				nodeInfo.AvailableResources.NanoCPUs += reservations.NanoCPUs

				for _, ep := range specContainer.ExposedPorts {
					if ep.HostPort == 0 {
						continue
					}
					if nodeInfo.ReservedPorts[ep.HostPort] != nil {
						delete(nodeInfo.ReservedPorts[ep.HostPort], t.ID)
						if len(nodeInfo.ReservedPorts[ep.HostPort]) == 0 {
							delete(nodeInfo.ReservedPorts, ep.HostPort)
						}
					}
				}
			}
			if statusContainer := t.Status.GetContainer(); statusContainer != nil {
				for _, ep := range statusContainer.ExposedPorts {
					if ep.HostPort == 0 {
						continue
					}
					if nodeInfo.ReservedPorts[ep.HostPort] != nil {
						delete(nodeInfo.ReservedPorts[ep.HostPort], t.ID)
						if len(nodeInfo.ReservedPorts[ep.HostPort]) == 0 {
							delete(nodeInfo.ReservedPorts, ep.HostPort)
						}
					}
				}

			}
			return true
		}
	}
	return false
}

func (nodeInfo *NodeInfo) addTask(t *api.Task) bool {
	if nodeInfo.Tasks == nil {
		nodeInfo.Tasks = make(map[string]*api.Task)
	}
	container := t.GetContainer()
	if _, ok := nodeInfo.Tasks[t.ID]; !ok {
		nodeInfo.Tasks[t.ID] = t
		if container != nil {
			specContainer := container.Spec
			reservations := taskReservations(&specContainer)
			nodeInfo.AvailableResources.MemoryBytes -= reservations.MemoryBytes
			nodeInfo.AvailableResources.NanoCPUs -= reservations.NanoCPUs

			for _, ep := range specContainer.ExposedPorts {
				if ep.HostPort == 0 {
					continue
				}
				if _, found := nodeInfo.ReservedPorts[ep.HostPort]; !found {
					nodeInfo.ReservedPorts[ep.HostPort] = make(map[string]struct{})
				}
				if _, found := nodeInfo.ReservedPorts[ep.HostPort][t.ID]; !found {
					nodeInfo.ReservedPorts[ep.HostPort][t.ID] = struct{}{}
				}
			}
		}
		return true
	}

	// If a task is not new to this node, it could have a new port
	// allocated.
	changes := false
	if statusContainer := t.Status.GetContainer(); statusContainer != nil {
		for _, ep := range statusContainer.ExposedPorts {
			if ep.HostPort == 0 {
				continue
			}
			if _, found := nodeInfo.ReservedPorts[ep.HostPort]; !found {
				nodeInfo.ReservedPorts[ep.HostPort] = make(map[string]struct{})
			}
			if _, found := nodeInfo.ReservedPorts[ep.HostPort][t.ID]; !found {
				changes = true
				nodeInfo.ReservedPorts[ep.HostPort][t.ID] = struct{}{}
			}
		}
	}
	return changes
}

func taskReservations(container *api.ContainerSpec) (reservations api.Resources) {
	if container != nil && container.Resources != nil && container.Resources.Reservations != nil {
		reservations = *container.Resources.Reservations
	}
	return
}
<commit_msg>scheduler: Make addTask and removeTask noops on empty NodeInfo structs<commit_after>package scheduler

import "github.com/docker/swarm-v2/api"

// NodeInfo contains a node and some additional metadata.
type NodeInfo struct {
	*api.Node
	Tasks              map[string]*api.Task
	AvailableResources api.Resources

	// There are some corner cases where we may assign multiple tasks that
	// need the same port to a single node. To deal with this properly,
	// ReservedPorts has a set of tasks using each port rather than just a
	// set of ports.
	ReservedPorts map[uint32]map[string]struct{}
}

func newNodeInfo(n *api.Node, tasks map[string]*api.Task, availableResources api.Resources) NodeInfo {
	nodeInfo := NodeInfo{
		Node:               n,
		Tasks:              make(map[string]*api.Task),
		AvailableResources: availableResources,
		ReservedPorts:      make(map[uint32]map[string]struct{}),
	}

	for _, t := range tasks {
		nodeInfo.addTask(t)
	}
	return nodeInfo
}

func (nodeInfo *NodeInfo) removeTask(t *api.Task) bool {
	if nodeInfo.Tasks == nil || nodeInfo.Node == nil {
		return false
	}
	if _, ok := nodeInfo.Tasks[t.ID]; !ok {
		return false
	}

	delete(nodeInfo.Tasks, t.ID)
	if t.GetContainer() != nil {
		specContainer := t.GetContainer().Spec
		reservations := taskReservations(&specContainer)
		nodeInfo.AvailableResources.MemoryBytes += reservations.MemoryBytes
		nodeInfo.AvailableResources.NanoCPUs += reservations.NanoCPUs

		for _, ep := range specContainer.ExposedPorts {
			if ep.HostPort == 0 {
				continue
			}
			if nodeInfo.ReservedPorts[ep.HostPort] != nil {
				delete(nodeInfo.ReservedPorts[ep.HostPort], t.ID)
				if len(nodeInfo.ReservedPorts[ep.HostPort]) == 0 {
					delete(nodeInfo.ReservedPorts, ep.HostPort)
				}
			}
		}
	}
	if statusContainer := t.Status.GetContainer(); statusContainer != nil {
		for _, ep := range statusContainer.ExposedPorts {
			if ep.HostPort == 0 {
				continue
			}
			if nodeInfo.ReservedPorts[ep.HostPort] != nil {
				delete(nodeInfo.ReservedPorts[ep.HostPort], t.ID)
				if len(nodeInfo.ReservedPorts[ep.HostPort]) == 0 {
					delete(nodeInfo.ReservedPorts, ep.HostPort)
				}
			}
		}

	}
	return true
}

func (nodeInfo *NodeInfo) addTask(t *api.Task) bool {
	if nodeInfo.Node == nil {
		return false
	}
	if nodeInfo.Tasks == nil {
		nodeInfo.Tasks = make(map[string]*api.Task)
	}
	container := t.GetContainer()
	if _, ok := nodeInfo.Tasks[t.ID]; !ok {
		nodeInfo.Tasks[t.ID] = t
		if container != nil {
			specContainer := container.Spec
			reservations := taskReservations(&specContainer)
			nodeInfo.AvailableResources.MemoryBytes -= reservations.MemoryBytes
			nodeInfo.AvailableResources.NanoCPUs -= reservations.NanoCPUs

			for _, ep := range specContainer.ExposedPorts {
				if ep.HostPort == 0 {
					continue
				}
				if _, found := nodeInfo.ReservedPorts[ep.HostPort]; !found {
					nodeInfo.ReservedPorts[ep.HostPort] = make(map[string]struct{})
				}
				if _, found := nodeInfo.ReservedPorts[ep.HostPort][t.ID]; !found {
					nodeInfo.ReservedPorts[ep.HostPort][t.ID] = struct{}{}
				}
			}
		}
		return true
	}

	// If a task is not new to this node, it could have a new port
	// allocated.
	changes := false
	if statusContainer := t.Status.GetContainer(); statusContainer != nil {
		for _, ep := range statusContainer.ExposedPorts {
			if ep.HostPort == 0 {
				continue
			}
			if _, found := nodeInfo.ReservedPorts[ep.HostPort]; !found {
				nodeInfo.ReservedPorts[ep.HostPort] = make(map[string]struct{})
			}
			if _, found := nodeInfo.ReservedPorts[ep.HostPort][t.ID]; !found {
				changes = true
				nodeInfo.ReservedPorts[ep.HostPort][t.ID] = struct{}{}
			}
		}
	}
	return changes
}

func taskReservations(container *api.ContainerSpec) (reservations api.Resources) {
	if container != nil && container.Resources != nil && container.Resources.Reservations != nil {
		reservations = *container.Resources.Reservations
	}
	return
}

{'fraction_non_alphanumeric': 0.1222336592897581, 'fraction_numerical': 0.0028306742151312406, 'mean_word_length': 3.467241379310345, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6619813', 'n_tokens_mistral': 2912, 'n_tokens_neox': 2533, 'n_words': 564}