mirror of
https://github.com/optim-enterprises-bv/kubernetes.git
synced 2025-11-01 18:58:18 +00:00
Since the GA graduation of memory manager in https://github.com/kubernetes/kubernetes/pull/128517 we are sharing the initial container map across managers. The intention of this sharing was not to actually share a data structure, but 1. save the relatively expensive relisting from runtime 2. have all the managers share a consistent view - even though the chance for misalignement tend to be tiny. The unwanted side effect though is now all the managers race to modify a data shared, not thread safe data structure. The fix is to clone (deepcopy) the computed map when passing it to each manager. This restores the old semantic of the code. This issue brings the topic of possibly managers go out of sync since each of them maintain a private view of the world. This risk is real, yet this is how the code worked for most of the lifetime, so the plan is to look at this and evaluate possible improvements later on. Signed-off-by: Francesco Romani <fromani@redhat.com>
91 lines
2.8 KiB
Go
91 lines
2.8 KiB
Go
/*
|
|
Copyright 2019 The Kubernetes Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package containermap
|
|
|
|
import (
|
|
"fmt"
|
|
)
|
|
|
|
// cmItem (ContainerMap ITEM) is a pair podUID, containerName
|
|
type cmItem struct {
|
|
podUID string
|
|
containerName string
|
|
}
|
|
|
|
// ContainerMap maps (containerID)->(podUID, containerName)
|
|
type ContainerMap map[string]cmItem
|
|
|
|
// NewContainerMap creates a new ContainerMap struct
|
|
func NewContainerMap() ContainerMap {
|
|
return make(ContainerMap)
|
|
}
|
|
|
|
// Clone creates a deep copy of the ContainerMap
|
|
func (cm ContainerMap) Clone() ContainerMap {
|
|
ret := make(ContainerMap, len(cm))
|
|
for key, val := range cm {
|
|
ret[key] = val
|
|
}
|
|
return ret
|
|
}
|
|
|
|
// Add adds a mapping of (containerID)->(podUID, containerName) to the ContainerMap
|
|
func (cm ContainerMap) Add(podUID, containerName, containerID string) {
|
|
cm[containerID] = cmItem{
|
|
podUID: podUID,
|
|
containerName: containerName,
|
|
}
|
|
}
|
|
|
|
// RemoveByContainerID removes a mapping of (containerID)->(podUID, containerName) from the ContainerMap
|
|
func (cm ContainerMap) RemoveByContainerID(containerID string) {
|
|
delete(cm, containerID)
|
|
}
|
|
|
|
// RemoveByContainerRef removes a mapping of (containerID)->(podUID, containerName) from the ContainerMap
|
|
func (cm ContainerMap) RemoveByContainerRef(podUID, containerName string) {
|
|
containerID, err := cm.GetContainerID(podUID, containerName)
|
|
if err == nil {
|
|
cm.RemoveByContainerID(containerID)
|
|
}
|
|
}
|
|
|
|
// GetContainerID retrieves a ContainerID from the ContainerMap
|
|
func (cm ContainerMap) GetContainerID(podUID, containerName string) (string, error) {
|
|
for key, val := range cm {
|
|
if val.podUID == podUID && val.containerName == containerName {
|
|
return key, nil
|
|
}
|
|
}
|
|
return "", fmt.Errorf("container %s not in ContainerMap for pod %s", containerName, podUID)
|
|
}
|
|
|
|
// GetContainerRef retrieves a (podUID, containerName) pair from the ContainerMap
|
|
func (cm ContainerMap) GetContainerRef(containerID string) (string, string, error) {
|
|
if _, exists := cm[containerID]; !exists {
|
|
return "", "", fmt.Errorf("containerID %s not in ContainerMap", containerID)
|
|
}
|
|
return cm[containerID].podUID, cm[containerID].containerName, nil
|
|
}
|
|
|
|
// Visit invoke visitor function to walks all of the entries in the container map
|
|
func (cm ContainerMap) Visit(visitor func(podUID, containerName, containerID string)) {
|
|
for k, v := range cm {
|
|
visitor(v.podUID, v.containerName, k)
|
|
}
|
|
}
|