...

Source file src/github.com/containerd/containerd/runtime/nsmap.go

Documentation: github.com/containerd/containerd/runtime

     1  /*
     2     Copyright The containerd Authors.
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  package runtime
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"sync"
    23  
    24  	"github.com/containerd/containerd/errdefs"
    25  	"github.com/containerd/containerd/namespaces"
    26  )
    27  
    28  type object interface {
    29  	ID() string
    30  }
    31  
    32  // NSMap extends Map type with a notion of namespaces passed via Context.
    33  type NSMap[T object] struct {
    34  	mu      sync.Mutex
    35  	objects map[string]map[string]T
    36  }
    37  
    38  // NewNSMap returns a new NSMap
    39  func NewNSMap[T object]() *NSMap[T] {
    40  	return &NSMap[T]{
    41  		objects: make(map[string]map[string]T),
    42  	}
    43  }
    44  
    45  // Get a task
    46  func (m *NSMap[T]) Get(ctx context.Context, id string) (T, error) {
    47  	m.mu.Lock()
    48  	defer m.mu.Unlock()
    49  	namespace, err := namespaces.NamespaceRequired(ctx)
    50  	var t T
    51  	if err != nil {
    52  		return t, err
    53  	}
    54  	tasks, ok := m.objects[namespace]
    55  	if !ok {
    56  		return t, errdefs.ErrNotFound
    57  	}
    58  	t, ok = tasks[id]
    59  	if !ok {
    60  		return t, errdefs.ErrNotFound
    61  	}
    62  	return t, nil
    63  }
    64  
    65  // GetAll objects under a namespace
    66  func (m *NSMap[T]) GetAll(ctx context.Context, noNS bool) ([]T, error) {
    67  	m.mu.Lock()
    68  	defer m.mu.Unlock()
    69  	var o []T
    70  	if noNS {
    71  		for ns := range m.objects {
    72  			for _, t := range m.objects[ns] {
    73  				o = append(o, t)
    74  			}
    75  		}
    76  		return o, nil
    77  	}
    78  	namespace, err := namespaces.NamespaceRequired(ctx)
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  	tasks, ok := m.objects[namespace]
    83  	if !ok {
    84  		return o, nil
    85  	}
    86  	for _, t := range tasks {
    87  		o = append(o, t)
    88  	}
    89  	return o, nil
    90  }
    91  
    92  // Add a task
    93  func (m *NSMap[T]) Add(ctx context.Context, t T) error {
    94  	namespace, err := namespaces.NamespaceRequired(ctx)
    95  	if err != nil {
    96  		return err
    97  	}
    98  	return m.AddWithNamespace(namespace, t)
    99  }
   100  
   101  // AddWithNamespace adds a task with the provided namespace
   102  func (m *NSMap[T]) AddWithNamespace(namespace string, t T) error {
   103  	m.mu.Lock()
   104  	defer m.mu.Unlock()
   105  
   106  	id := t.ID()
   107  	if _, ok := m.objects[namespace]; !ok {
   108  		m.objects[namespace] = make(map[string]T)
   109  	}
   110  	if _, ok := m.objects[namespace][id]; ok {
   111  		return fmt.Errorf("%s: %w", id, errdefs.ErrAlreadyExists)
   112  	}
   113  	m.objects[namespace][id] = t
   114  	return nil
   115  }
   116  
   117  // Delete a task
   118  func (m *NSMap[T]) Delete(ctx context.Context, id string) {
   119  	m.mu.Lock()
   120  	defer m.mu.Unlock()
   121  	namespace, err := namespaces.NamespaceRequired(ctx)
   122  	if err != nil {
   123  		return
   124  	}
   125  	tasks, ok := m.objects[namespace]
   126  	if ok {
   127  		delete(tasks, id)
   128  	}
   129  }
   130  
   131  func (m *NSMap[T]) IsEmpty() bool {
   132  	m.mu.Lock()
   133  	defer m.mu.Unlock()
   134  
   135  	for ns := range m.objects {
   136  		if len(m.objects[ns]) > 0 {
   137  			return false
   138  		}
   139  	}
   140  
   141  	return true
   142  }
   143  

View as plain text